
package com.jf.cloud.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.jf.cloud.api.auth.constant.SysTypeEnum;
import com.jf.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.jf.cloud.api.delivery.dto.DeliveryOrderItemDTO;
import com.jf.cloud.api.delivery.feign.AreaFeignClient;
import com.jf.cloud.api.delivery.feign.DeliveryCompanyFeignClient;
import com.jf.cloud.api.delivery.feign.DeliveryFeignClient;
import com.jf.cloud.api.delivery.feign.StationFeignClient;
import com.jf.cloud.api.delivery.vo.StationVO;
import com.jf.cloud.api.feign.SearchOrderFeignClient;
import com.jf.cloud.api.feign.SearchSpuFeignClient;
import com.jf.cloud.api.leaf.dto.SegmentDTO;
import com.jf.cloud.api.leaf.feign.SegmentFeignClient;
import com.jf.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.jf.cloud.api.multishop.vo.ShopDetailVO;
import com.jf.cloud.api.order.bo.DeleteShopCartItemMessageBO;
import com.jf.cloud.api.order.bo.DistributionAmountWithOrderIdBO;
import com.jf.cloud.api.order.constant.OrderStatus;
import com.jf.cloud.api.order.constant.PreSalePayStatus;
import com.jf.cloud.api.order.constant.PurchaseOrderWaitStatus;
import com.jf.cloud.api.order.vo.OrderAmountVO;
import com.jf.cloud.api.payment.dto.OrderPayInfoDTO;
import com.jf.cloud.api.payment.feign.PaymentFeignClient;
import com.jf.cloud.api.product.bo.PlatformCommissionItemBO;
import com.jf.cloud.api.product.bo.PlatformCommissionOrderItemBO;
import com.jf.cloud.api.product.feign.*;
import com.jf.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.jf.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.jf.cloud.api.user.bo.UserScoreBO;
import com.jf.cloud.api.user.dto.ShopCustomerReqDTO;
import com.jf.cloud.api.user.dto.UserTypeDTO;
import com.jf.cloud.api.user.feign.ShopCustomerFeignClient;
import com.jf.cloud.api.user.feign.UserLevelAndScoreOrderFeignClient;
import com.jf.cloud.api.user.feign.UserLevelLogClient;
import com.jf.cloud.api.vo.EsPageVO;
import com.jf.cloud.common.constant.*;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.i18n.I18nMessage;
import com.jf.cloud.common.i18n.LanguageEnum;
import com.jf.cloud.common.order.bo.EsOrderBO;
import com.jf.cloud.common.order.bo.EsOrderItemBO;
import com.jf.cloud.common.order.bo.OrderStatusBO;
import com.jf.cloud.common.order.bo.PayNotifyBO;
import com.jf.cloud.common.order.constant.DeliveryType;
import com.jf.cloud.common.order.constant.OrderActivityType;
import com.jf.cloud.common.order.constant.OrderType;
import com.jf.cloud.common.order.dto.DvyTypeDTO;
import com.jf.cloud.common.order.dto.OrderDTO;
import com.jf.cloud.common.order.dto.OrderInvoiceDTO;
import com.jf.cloud.common.order.dto.OrderSearchDTO;
import com.jf.cloud.common.order.util.OrderLangUtil;
import com.jf.cloud.common.order.vo.*;
import com.jf.cloud.common.product.constant.PreSaleType;
import com.jf.cloud.common.product.constant.SpuMold;
import com.jf.cloud.common.product.dto.ProductSearchDTO;
import com.jf.cloud.common.product.vo.GiveawaySpuVO;
import com.jf.cloud.common.product.vo.GiveawayVO;
import com.jf.cloud.common.product.vo.SkuVO;
import com.jf.cloud.common.product.vo.SpuVO;
import com.jf.cloud.common.product.vo.search.SpuAdminVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.rocketmq.config.RocketMqConstant;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.common.util.Arith;
import com.jf.cloud.common.util.Json;
import com.jf.cloud.common.util.LangUtil;
import com.jf.cloud.common.util.PriceUtil;
import com.jf.cloud.order.bo.SubmitOrderPayAmountInfoBO;
import com.jf.cloud.order.bo.mongo.MongoOrderBO;
import com.jf.cloud.order.bo.mongo.MongoOrderItemBO;
import com.jf.cloud.order.constant.RefundStatusEnum;
import com.jf.cloud.order.constant.RefundType;
import com.jf.cloud.order.dto.multishop.OrderAdminDTO;
import com.jf.cloud.order.dto.multishop.OrderItemDTO;
import com.jf.cloud.order.manager.MongoOrderManager;
import com.jf.cloud.order.mapper.OrderMapper;
import com.jf.cloud.order.mapper.OrderRefundMapper;
import com.jf.cloud.order.mapper.OrderSettlementMapper;
import com.jf.cloud.order.model.*;
import com.jf.cloud.order.service.*;
import com.jf.cloud.order.vo.OrderAndPreSaleVO;
import com.jf.cloud.order.vo.OrderOverviewVO;
import com.jf.cloud.order.vo.OrderRefundVO;
import io.seata.spring.annotation.GlobalTransactional;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单信息
 *
 * @author zz
 * @date 2020-12-05 14:13:50
 */
@Service
public class OrderServiceImpl implements OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);


    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RocketMQTemplate orderPurchaseNotifyShopTemplate;
    @Autowired
    private RocketMQTemplate deleteShopCartItemTemplate;
    @Autowired
    private OrderSettlementMapper orderSettlementMapper;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderItemLangService orderItemLangService;
    @Autowired
    private OrderPreSaleInfoService orderPreSaleInfoService;
    @Autowired
    private OrderRefundMapper orderRefundMapper;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private CategoryShopFeignClient categoryShopFeignClient;
    @Autowired
    private DeliveryFeignClient deliveryFeignClient;
    @Autowired
    private DeliveryCompanyFeignClient deliveryCompanyFeignClient;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private OrderSettlementService orderSettlementService;
    @Autowired
    private ShopCartFeignClient shopCartFeignClient;
    @Autowired
    private CategoryFeignClient categoryFeignClient;
    @Autowired
    private SearchOrderFeignClient searchOrderFeignClient;
    @Autowired
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private RocketMQTemplate stockMqTemplate;
    @Autowired
    private RocketMQTemplate couponMqTemplate;
    @Autowired
    private RocketMQTemplate orderCancelTemplate;
    @Autowired
    private RocketMQTemplate outStockLogTemplate;
    @Autowired
    private RocketMQTemplate sendNotifyToUserTemplate;
    @Autowired
    private RocketMQTemplate groupOrderCancelMqTemplate;
    @Autowired
    private RocketMQTemplate seckillOrderCancelMqTemplate;
    @Autowired
    private RocketMQTemplate userScoreTemplate;
    @Autowired
    private MongoOrderManager mongoOrderManager;
    @Autowired
    private OrderInvoiceService orderInvoiceService;
    @Autowired
    private PaymentFeignClient paymentFeignClient;
    @Autowired
    private SegmentFeignClient segmentFeignClient;
    @Autowired
    private SpuFeignClient spuFeignClient;
    @Autowired
    private SkuFeignClient skuFeignClient;
    @Autowired
    private UserLevelLogClient userLevelLogClient;
    @Autowired
    private RocketMQTemplate sendNotifyToShopTemplate;
    @Autowired
    private OrderSelfStationService orderSelfStationService;
    @Autowired
    private StationFeignClient stationFeignClient;
    @Autowired
    private ShopCustomerFeignClient shopCustomerFeignClient;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;
    @Autowired
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private AreaFeignClient areaFeignClient;
    @Autowired
    private UserLevelAndScoreOrderFeignClient userLevelAndScoreOrderFeignClient;
    @Autowired
    private SupplierDetailFeignClient supplierDetailFeignClient;

    @Override
    public Order getByOrderId(Long orderId) {
        return orderMapper.getByOrderId(orderId);
    }

    @Override
    public void update(Order order) {
        orderMapper.update(order);
    }

    @Override
    public void deleteById(Long orderId) {
        orderMapper.deleteById(orderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<Long> submit(ShopCartOrderMergerVO mergerOrder) {
        Long userId = mergerOrder.getUserId();
        List<Long> orderIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 订单商品参数
        List<ShopCartOrderVO> shopCartOrders = mergerOrder.getShopCartOrders();

        List<OrderSettlement> orderSettlements = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Order> orders = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<OrderItem> orderItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<OrderItem> giveawayOrderItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<OrderPreSaleInfo> orderPreSaleInfos = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<Long> shopCartItemIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        OrderAddr orderAddr = mapperFacade.map(mergerOrder.getUserAddr(), OrderAddr.class);
        if (Objects.nonNull(mergerOrder.getUserAddr())) {
            orderAddr.setOrderAddrId(mergerOrder.getUserAddr().getAddrId());
        }
        List<Integer> dvyList = mergerOrder.getDvyTypes().stream().map(DvyTypeDTO::getDvyType).collect(Collectors.toList());
        // 快递和同城配送的地址信息
        if (dvyList.contains(DeliveryType.DELIVERY.value()) && Objects.isNull(orderAddr)) {
            // 请填写收货地址
            throw new LuckException("请填写收货地址");
        }
        Map<Long, List<VirtualRemarkVO>> virtualRemarkMap = new HashMap<>(8);
        // 虚拟商品备注信息列表
        if (CollUtil.isNotEmpty(mergerOrder.getVirtualRemarkList())) {
            virtualRemarkMap = mergerOrder.getVirtualRemarkList().stream().collect(Collectors.groupingBy(VirtualRemarkVO::getSpuId));
        }
        Map<Long, Integer> dvyTypeMap = mergerOrder.getDvyTypes().stream().collect(Collectors.toMap(DvyTypeDTO::getShopId, DvyTypeDTO::getDvyType));
        // 每个店铺生成一个订单
        for (ShopCartOrderVO shopCartOrderDto : shopCartOrders) {
            Order order = getOrder(userId, dvyTypeMap.get(shopCartOrderDto.getShopId()), mergerOrder.getSpuMold(), shopCartOrderDto);
            saveOrderInvoice(mergerOrder, order);
            addOrderSettlement(mergerOrder, userId, orderSettlements, shopCartOrderDto, order);

            List<ShopCartItemDiscountVO> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
            for (ShopCartItemDiscountVO shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemVO> shopCartItems = shopCartItemDiscount.getShopCartItems();
                for (ShopCartItemVO shopCartItem : shopCartItems) {
                    if (!Objects.equals(shopCartItem.getCartItemId(), 0L)) {
                        shopCartItemIds.add(shopCartItem.getCartItemId());
                    }
                    if (order.getOrderItems() == null) {
                        order.setOrderItems(new ArrayList<>(0));
                    }
                    OrderItem orderItem = getOrderItem(mergerOrder, order, shopCartItem, virtualRemarkMap, shopCartOrderDto);
                    orderItems.add(orderItem);
                    order.getOrderItems().add(orderItem);
                    handleGiveaway(giveawayOrderItems, order, shopCartItem, orderItem);
                    handlePreSaleInfo(orderPreSaleInfos, order, shopCartItem);
                }
            }
            setOrderAddrId(orderAddr, order);
            orders.add(order);
            orderIds.add(order.getOrderId());
            // 处理自提和同城配送的订单
            int dvyType = dvyTypeMap.get(shopCartOrderDto.getShopId());
            deliverySubmitOrderListener(mergerOrder, order, dvyType, userId);
            // 处理下虚拟商品订单
            handlerVirtualProdOder(mergerOrder, shopCartOrderDto, order, userId);
        }

        // 添加赠品订单项
        if (CollUtil.isNotEmpty(giveawayOrderItems)) {
            orderItems.addAll(giveawayOrderItems);
        }

        saveInfo(orderSettlements, orders, orderItems, orderPreSaleInfos, orderAddr);

        sendMsg(mergerOrder, shopCartItemIds, orderIds);
        //店铺客户
        saveShopCustomer(mergerOrder);
        return orderIds;
    }
    private void saveInfo(List<OrderSettlement> orderSettlements, List<Order> orders, List<OrderItem> orderItems, List<OrderPreSaleInfo> orderPreSaleInfos, OrderAddr orderAddr) {
        // 保存收货地址
        if (Objects.nonNull(orderAddr)) {
            // 保存收货地址
            orderAddrService.save(orderAddr);
        }

        orderMapper.saveBatch(orders);
        orderItemService.saveBatch(orderItems);
        orderItemLangService.saveOrderItemLang(orderItems);

        for (OrderSettlement orderSettlement : orderSettlements) {
            orderSettlementMapper.save(orderSettlement);
        }
        // 保存预售信息
        if (CollectionUtil.isNotEmpty(orderPreSaleInfos)) {
            orderPreSaleInfoService.saveBatch(orderPreSaleInfos);
        }
    }

    private void saveShopCustomer(ShopCartOrderMergerVO mergerOrder) {
        mergerOrder.getShopCartOrders().get(0).setUserId(mergerOrder.getUserId());
        Set<Long> shopIdList = mergerOrder.getShopCartOrders().stream().map(ShopCartOrderVO::getShopId).collect(Collectors.toSet());
        ShopCustomerReqDTO shopCustomerReqDTO = new ShopCustomerReqDTO();
        shopCustomerReqDTO.setUserId(mergerOrder.getUserId());
        shopCustomerReqDTO.setShopIds(new ArrayList<>(shopIdList));
        shopCustomerFeignClient.saveBatchByOrders(shopCustomerReqDTO);
    }

    private void sendMsg(ShopCartOrderMergerVO mergerOrder, List<Long> shopCartItemIds,  List<Long> orderIds) {
        // 发送消息，清空购物车
        if (CollUtil.isNotEmpty(shopCartItemIds)) {
            DeleteShopCartItemMessageBO deleteShopCartItemMessageBO = new DeleteShopCartItemMessageBO();
            deleteShopCartItemMessageBO.setShopCartItemIds(shopCartItemIds);
            deleteShopCartItemMessageBO.setUserId(AuthUserContext.get().getUserId());
            SendStatus deleteShopCartItemStatus = deleteShopCartItemTemplate.syncSend(RocketMqConstant.DELETE_SHOP_CART_ITEM_TOPIC, new GenericMessage<>(deleteShopCartItemMessageBO)).getSendStatus();
            if (!Objects.equals(deleteShopCartItemStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }

        // 发送消息，如果三十分钟后没有支付，则取消订单
        SendStatus sendStatus = orderCancelTemplate.syncSend(RocketMqConstant.ORDER_CANCEL_TOPIC, new GenericMessage<>(orderIds), RocketMqConstant.TIMEOUT, RocketMqConstant.CANCEL_ORDER_DELAY_LEVEL).getSendStatus();
        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
            // 消息发不出去就抛异常，发的出去无所谓
            throw new LuckException(ResponseEnum.EXCEPTION);
        }

        // 生成出库明细
        SendStatus sendStockStatus = outStockLogTemplate.syncSend(RocketMqConstant.OUT_STOCK_LOG_TOPIC, new GenericMessage<>(mergerOrder.getShopCartOrders())).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            // 消息发不出去就抛异常，发的出去无所谓
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    private void handleGiveaway(List<OrderItem> giveawayOrderItems, Order order, ShopCartItemVO shopCartItem, OrderItem orderItem) {
        // 赠品
        List<OrderItem> orderItemList = giveawayOrderItems(order, shopCartItem);
        if (CollectionUtil.isNotEmpty(orderItemList)) {
            orderItem.setMainGiveaway(1);
            giveawayOrderItems.addAll(orderItemList);
        }
    }

    private void handlePreSaleInfo(List<OrderPreSaleInfo> orderPreSaleInfos, Order order, ShopCartItemVO shopCartItem) {
        // 如果是预售商品保存下下预售信息
        if (Objects.nonNull(shopCartItem.getPreSaleType()) && !Objects.equals(shopCartItem.getPreSaleType(), PreSaleType.DISABLE.value())) {
            order.setPreSaleType(shopCartItem.getPreSaleType());
            OrderPreSaleInfo orderPreSaleInfo = getOrderPresaleInfo(order, shopCartItem);
            orderPreSaleInfo.setUserId(order.getUserId());
            orderPreSaleInfos.add(orderPreSaleInfo);
        }
    }

    private static void setOrderAddrId(OrderAddr orderAddr, Order order) {
        if (Objects.nonNull(orderAddr)) {
            order.setOrderAddrId(orderAddr.getOrderAddrId());
        } else {
            order.setOrderAddrId(0L);
        }
    }

    private static void addOrderSettlement(ShopCartOrderMergerVO mergerOrder, Long userId, List<OrderSettlement> orderSettlements, ShopCartOrderVO shopCartOrderDto, Order order) {
        // 插入订单结算表
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setSettlementId(shopCartOrderDto.getSettlementId());
        orderSettlement.setUserId(userId);
        orderSettlement.setIsClearing(0);
        orderSettlement.setOrderId(order.getOrderId());
        orderSettlement.setPayAmount(order.getActualTotal());
        orderSettlement.setVersion(0);
        //如果用使用积分，结算表将积分价格插入
        if (mergerOrder.getIsScorePay() != null && mergerOrder.getIsScorePay() == 1) {
            orderSettlement.setPayScore(shopCartOrderDto.getUseScore());
        } else {
            orderSettlement.setPayScore(0L);
        }
        orderSettlements.add(orderSettlement);
    }

    private void saveOrderInvoice(ShopCartOrderMergerVO mergerOrder, Order order) {
        //保存发票信息，每个店铺一个
        if (CollectionUtil.isNotEmpty(mergerOrder.getOrderInvoiceList())) {
            for (OrderInvoiceDTO orderInvoiceDTO : mergerOrder.getOrderInvoiceList()) {
                if (Objects.equals(order.getShopId(), orderInvoiceDTO.getShopId())) {
                    OrderInvoice orderInvoice = mapperFacade.map(orderInvoiceDTO, OrderInvoice.class);
                    orderInvoice.setInvoiceState(1);
                    orderInvoice.setInvoiceType(1);
                    orderInvoice.setInvoiceContext(1);
                    orderInvoice.setApplicationTime(new Date());
                    orderInvoice.setOrderId(order.getOrderId());
                    orderInvoice.setShopId(order.getShopId());
                    orderInvoiceService.save(order.getUserId(), orderInvoice);
                }
            }
        }
    }

    /**
     * 计算分摊金额
     */
    private void calculatePlatformCommission(List<Order> orders, List<OrderItem> orderItems) {
        List<PlatformCommissionOrderItemBO> platformCommissionOrderItems = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            PlatformCommissionOrderItemBO platformCommissionOrderItemBO = new PlatformCommissionOrderItemBO();
            PlatformCommissionItemBO platformCommissionShop = new PlatformCommissionItemBO();
            platformCommissionShop.setShopId(orderItem.getShopId());
            platformCommissionShop.setSysType(SysTypeEnum.MULTISHOP.value());
            platformCommissionOrderItemBO.setShopItem(platformCommissionShop);
            // 如果有供应商也放进去
            if (!Objects.equals(orderItem.getSupplierId(), 0L)) {
                PlatformCommissionItemBO platformCommissionSupplierItem = new PlatformCommissionItemBO();
                platformCommissionSupplierItem.setShopId(orderItem.getSupplierId());
                platformCommissionSupplierItem.setSysType(SysTypeEnum.SUPPLIER.value());
                platformCommissionOrderItemBO.setSupplierItem(platformCommissionSupplierItem);
            }
            platformCommissionOrderItemBO.setCategoryId(orderItem.getCategoryId());
            platformCommissionOrderItemBO.setSkuId(orderItem.getSkuId());
            platformCommissionOrderItems.add(platformCommissionOrderItemBO);
        }


        ServerResponseEntity<List<PlatformCommissionOrderItemBO>> listServerResponseEntity = categoryShopFeignClient.calculatePlatformCommission(platformCommissionOrderItems);
        if (!listServerResponseEntity.isSuccess()) {
            throw new LuckException(listServerResponseEntity);
        }


        List<PlatformCommissionOrderItemBO> data = listServerResponseEntity.getData();
        for (OrderItem orderItem : orderItems) {
            for (PlatformCommissionOrderItemBO platformCommissionOrderItemBO : data) {
                // 积分订单属于平台的订单不需要计算平台佣金
                if (Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value())) {
                    // 分摊比例
                    orderItem.setRate(0.0);
                    // 平台佣金
                    orderItem.setPlatformCommission(0L);
                    orderItem.setSupplierRate(0.0);
                    orderItem.setPurchasePlatformCommission(0L);
                    continue;
                }
                //赠品订单不需要计算佣金
                if (Objects.equals(orderItem.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                    // 分摊比例
                    orderItem.setRate(0.0);
                    // 平台佣金
                    orderItem.setPlatformCommission(0L);
                    orderItem.setSupplierRate(0.0);
                    orderItem.setPurchasePlatformCommission(0L);
                    break;
                }
                // 通过商品确定订单项
                if (Objects.equals(orderItem.getSkuId(), platformCommissionOrderItemBO.getSkuId())) {
                    // 分摊比例
                    orderItem.setRate(platformCommissionOrderItemBO.getRate());
                    // 平台佣金,如果是商家代销，供应商采购价的佣金也需要计算
                    // 平台对商家的差价抽佣 = （商家定的销售价格 - 供应商价格）-（商家定的销售价格 - 供应商价格）* 平台抽佣百分比
                    // 平台对商家的差价抽佣 = （用户实付金额 + 平台优惠金额 - 供应商金额） * 比例
                    long shopAmount = orderItem.getActualTotal() + orderItem.getPlatformShareReduce() - orderItem.getItemPurchaseAmount();
                    shopAmount = Math.max(shopAmount, 0L);
                    orderItem.setPlatformCommission(PriceUtil.divideByBankerRounding((long) ((shopAmount) * platformCommissionOrderItemBO.getRate()), 100));
                    orderItem.setSupplierRate(0.0);
                    orderItem.setPurchasePlatformCommission(0L);
                    if (!Objects.equals(orderItem.getSupplierId(), 0L)) {
                        // 供应商没有平台优惠，此时不用加上平台优惠进行计算
                        // 平台对供应商的抽佣 = 供应商定价 * 平台抽佣百分比
                        orderItem.setPurchasePlatformCommission(PriceUtil.divideByBankerRounding((long) (orderItem.getItemPurchaseAmount() * platformCommissionOrderItemBO.getSupplierRate()), 100));
                        orderItem.setSupplierRate(platformCommissionOrderItemBO.getSupplierRate());
                    }
                }
            }
        }
        Map<Long, List<OrderItem>> orderIdMap = orderItems.stream().collect(Collectors.groupingBy(OrderItem::getOrderId));
        for (Order order : orders) {
            Long totalPlatformCommission = 0L;
            List<OrderItem> orderItemList = orderIdMap.get(order.getOrderId());
            for (OrderItem orderItem : orderItemList) {
                totalPlatformCommission += orderItem.getPlatformCommission();
            }
            order.setPlatformCommission(totalPlatformCommission);
        }

    }

    @Override
    public List<OrderStatusBO> getOrdersStatus(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>();
        }
        List<OrderStatusBO> orderStatusList = orderMapper.getOrdersStatus(orderIds);
        for (Long orderId : orderIds) {
            boolean hasOrderId = false;
            for (OrderStatusBO orderStatusBO : orderStatusList) {
                if (Objects.equals(orderStatusBO.getOrderId(), orderId)) {
                    hasOrderId = true;
                    break;
                }
            }
            if (!hasOrderId) {
                OrderStatusBO orderStatusBO = new OrderStatusBO();
                orderStatusBO.setOrderId(orderId);
                orderStatusList.add(orderStatusBO);
            }
        }
        return orderStatusList;
    }

    @Override
    public OrderAmountVO getOrdersActualAmount(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return null;
        }
        List<OrderAndPreSaleVO> orderAmountList = orderMapper.listOrderActualAmount(orderIds);
        OrderAmountVO orderAmountVO = new OrderAmountVO();
        orderAmountVO.setPayAmount(0L);
        for (OrderAndPreSaleVO orderVO : orderAmountList) {
            orderAmountVO.setPayScore(orderVO.getOrderScore());
            // 定金预售判断
            boolean flag = Objects.equals(orderVO.getPreSaleType(), PreSaleType.DEPOSIT.value());
            if (flag && Objects.equals(orderVO.getStatus(), OrderStatus.UNPAY.value())) {
                orderAmountVO.setPayAmount(orderAmountVO.getPayAmount() + orderVO.getDepositAmount());
                continue;
            }
            Long balanceAmount = orderVO.getBalanceAmount() + orderVO.getFreightAmount() - orderVO.getPlatformFreeFreightAmount();
            if (flag && Objects.equals(orderVO.getStatus(), OrderStatus.WAIT_BALANCE.value()) && balanceAmount <= 0L) {
                throw new LuckException("尾款为0，无需进行支付尾款");
            }
            if (flag && Objects.equals(orderVO.getStatus(), OrderStatus.WAIT_BALANCE.value())) {
                // 如果是支付尾款还需要加上运费
                orderAmountVO.setPayAmount(orderAmountVO.getPayAmount() + orderVO.getBalanceAmount() + orderVO.getFreightAmount());
                continue;
            }

            orderAmountVO.setPayAmount(orderAmountVO.getPayAmount() + orderVO.getActualTotal());
        }
        return orderAmountVO;
    }

//    @Override
//    public boolean isPay(Long orderId, Long userId) {
//        return BooleanUtil.isTrue(orderMapper.isPay(orderId, userId));
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateByToPaySuccess(PayNotifyBO message, List<OrderStatusBO> ordersStatus) {
        if (CollectionUtil.isEmpty(ordersStatus)) {
            log.error("无法找到订单信息，message: + " + Json.toJsonString(message));
            return;
        }
        ordersStatus = ordersStatus.stream()
                .filter(orderStatusBO -> Objects.equals(orderStatusBO.getStatus(), OrderStatus.UNPAY.value()) || Objects.equals(orderStatusBO.getStatus(), OrderStatus.WAIT_BALANCE.value()))
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(ordersStatus)) {
            return;
        }
        List<Long> needUpdateOrderIds = ordersStatus.stream().map(OrderStatusBO::getOrderId).collect(Collectors.toList());
        Integer orderType = ordersStatus.get(0).getOrderType();
        Long actualTotal = 0L;
        StringBuilder payIds = new StringBuilder();
        // 团购订单
        if (Objects.equals(orderType, OrderType.GROUP.value())) {
            // 待成团
            orderMapper.updateByToGroupPaySuccess(needUpdateOrderIds, message.getPayType());
        } else {
            for (OrderStatusBO esOrderVO : ordersStatus) {
                // 待发货 或待收货
                orderMapper.updateByToPaySuccess(esOrderVO, message.getPayType());
            }
        }
        // 预售信息处理,并且获取当前已经支付的金额
        actualTotal = handleOrderPreSale(needUpdateOrderIds, ordersStatus, message, payIds);
        orderSettlementMapper.updateToPaySuccess(needUpdateOrderIds, message.getPayId(), message.getPayType(), payIds.toString(), actualTotal);

    }

    private Long handleOrderPreSale(List<Long> needUpdateOrderIds, List<OrderStatusBO> ordersStatusList, PayNotifyBO payNotifyBO, StringBuilder payIds) {
        Integer statusDb = ordersStatusList.get(0).getStatus();
        long payAmount = 0L;
        List<OrderPreSaleInfo> orderPreSaleInfoList = orderPreSaleInfoService.listByOrderIds(needUpdateOrderIds);
        // 如果为空则不需要处理预售信息，且不需要修改金额
        if (CollectionUtil.isEmpty(orderPreSaleInfoList)) {
            return 0L;
        }
        // 如果是定金预售，还需要修改下订单支付后的状态
        if (Objects.equals(orderPreSaleInfoList.get(0).getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            // 定金预售订单，1.待付尾款 2.待发货
            orderMapper.updateByToPreSaleSuccess(needUpdateOrderIds, statusDb);
        }
        // 处理下预售的发货时间
        for (OrderPreSaleInfo orderPreSaleInfo : orderPreSaleInfoList) {
            if (Objects.equals(orderPreSaleInfo.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
                orderPreSaleInfo.setPayStatus(Objects.equals(statusDb, OrderStatus.UNPAY.value()) ? PreSalePayStatus.PAYED_DEPOSIT.value() : PreSalePayStatus.PAYED_BALANCE.value());
                //尾款支付时间
                orderPreSaleInfo.setBalancePayTime(Objects.equals(statusDb, OrderStatus.UNPAY.value()) ? null : new Date());
                // 定金预售,待支付时支付后的实付金额为定金
                payAmount = Objects.equals(statusDb, OrderStatus.UNPAY.value()) ? orderPreSaleInfo.getDepositAmount() : ordersStatusList.get(0).getActualTotal();
                // 如果发货时间不是固定时间，且为支付尾款设置下发货时间
                if (!Objects.equals(orderPreSaleInfo.getPreSaleDeliveryType(), -1) && Objects.equals(statusDb, OrderStatus.WAIT_BALANCE.value())) {
                    orderPreSaleInfo.setPreSaleDeliveryTime(DateUtil.offsetDay(new DateTime(), orderPreSaleInfo.getPreSaleDeliveryType()));
                }
            } else if (!Objects.equals(orderPreSaleInfo.getPreSaleDeliveryType(), -1)) {
                // 如果全款预售发货时间不是固定时间，设置下发货时间
                orderPreSaleInfo.setPreSaleDeliveryTime(DateUtil.offsetDay(new DateTime(), orderPreSaleInfo.getPreSaleDeliveryType()));
            }
        }
        if (CollectionUtil.isNotEmpty(orderPreSaleInfoList)) {
            orderPreSaleInfoService.updateBatch(orderPreSaleInfoList);
        }
        if (Objects.equals(statusDb, OrderStatus.WAIT_BALANCE.value())) {
            OrderSettlement orderSettlement = orderSettlementMapper.getByOrderId(needUpdateOrderIds.get(0));
            orderSettlement.setPayAmount(orderSettlement.getPayAmount());
            if (Objects.nonNull(payNotifyBO.getPayId())) {
                payIds.append(orderSettlement.getPayId()).append(StrUtil.COMMA).append(payNotifyBO.getPayId());
            }else{
                payIds.append(orderSettlement.getPayId());
            }
        }
        return payAmount;
    }

    @Override
    public List<OrderSimpleAmountInfoBO> getOrdersSimpleAmountInfo(List<Long> orderIds) {


        List<OrderSimpleAmountInfoBO> ordersSimpleAmountInfos = orderMapper.getOrdersSimpleAmountInfo(orderIds);
        Map<Long, List<OrderRefundVO>> refundMap;
        if (CollUtil.isNotEmpty(orderIds)) {
            List<OrderRefundVO> refunds = orderRefundMapper.getProcessOrderRefundByOrderIds(orderIds);
            List<Long> itemIds = refunds.stream().map(OrderRefundVO::getOrderItemId).filter(itemId -> !Objects.equals(itemId, 0L)).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(itemIds)) {
                List<OrderItem> orderItems = orderItemService.listByIds(itemIds);
                Map<Long, OrderItem> orderItemMap = orderItems.stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
                for (OrderRefundVO refund : refunds) {
                    if (orderItemMap.containsKey(refund.getOrderItemId())) {
                        OrderItem orderItem = orderItemMap.get(refund.getOrderItemId());
                        refund.setItemPurchaseAmount(orderItem.getItemPurchaseAmount());
                        refund.setActualTotal(orderItem.getActualTotal());
                        refund.setPurPlatformRefundCommission(orderItem.getPurchasePlatformCommission());
                    }
                }
            }
            refundMap = refunds.stream().collect(Collectors.groupingBy(OrderRefundVO::getOrderId));
        } else {
            refundMap = new HashMap<>();
        }
        List<DistributionAmountWithOrderIdBO> distributionAmountWithOrderIds = orderItemService.sumTotalDistributionAmountByOrderIds(orderIds);

        for (OrderSimpleAmountInfoBO ordersSimpleAmountInfo : ordersSimpleAmountInfos) {
            long purchaseAmount = 0L;
            long actualTotal = 0L;
            long purchasePlatformCommission = 0L;
            if (refundMap.containsKey(ordersSimpleAmountInfo.getOrderId()) && !Objects.equals(ordersSimpleAmountInfo.getSupplierId(), 0L)) {
                // 减去退款的实付金额，采购金额，采购佣金
                List<OrderRefundVO> orderRefunds = refundMap.get(ordersSimpleAmountInfo.getOrderId());
                for (OrderRefundVO orderRefund : orderRefunds) {
                    if (orderRefund.getItemPurchaseAmount() == null) {
                        continue;
                    }
                    purchaseAmount += orderRefund.getItemPurchaseAmount();
                    actualTotal += orderRefund.getActualTotal();
                    purchasePlatformCommission += orderRefund.getPurPlatformRefundCommission();
                }
                ordersSimpleAmountInfo.setPurchaseAmount(ordersSimpleAmountInfo.getPurchaseAmount() - purchaseAmount);
                ordersSimpleAmountInfo.setActualTotal(ordersSimpleAmountInfo.getActualTotal() - actualTotal);
                ordersSimpleAmountInfo.setPurchasePlatformCommission(ordersSimpleAmountInfo.getPurchasePlatformCommission() - purchasePlatformCommission);
            }

            ordersSimpleAmountInfo.setShopAmount(ordersSimpleAmountInfo.getReduceAmount() - ordersSimpleAmountInfo.getPlatformAmount());
            Long orderId = ordersSimpleAmountInfo.getOrderId();
            ordersSimpleAmountInfo.setDistributionAmount(0L);
//            ordersSimpleAmountInfo.setPurchaseAmount(0L);
//            ordersSimpleAmountInfo.setPlatformSupplierCommission(0L);
            // 订单总分销金额
            for (DistributionAmountWithOrderIdBO distributionAmountWithOrderId : distributionAmountWithOrderIds) {
                if (Objects.equals(distributionAmountWithOrderId.getOrderId(), orderId)) {
                    ordersSimpleAmountInfo.setDistributionAmount(distributionAmountWithOrderId.getDistributionAmount() + distributionAmountWithOrderId.getDistributionParentAmount());
//                    ordersSimpleAmountInfo.setPurchaseAmount(ordersSimpleAmountInfo.getPurchaseAmount() + distributionAmountWithOrderId.getItemPurchaseAmount());
//                    ordersSimpleAmountInfo.setPlatformSupplierCommission(ordersSimpleAmountInfo.getPlatformSupplierCommission() + distributionAmountWithOrderId.getPurchasePlatformCommission());
                }
            }
        }

        return ordersSimpleAmountInfos;
    }

    /**
     * 取消订单和mq日志要同时落地
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrderAndGetCancelOrderIds(List<Long> orderIds) {
        List<OrderStatusBO> ordersStatus = this.getOrdersStatus(orderIds);
        List<Long> cancelOrderIds = new ArrayList<>();
        Integer orderType = null;
        for (OrderStatusBO orderStatusBO : ordersStatus) {
            if (orderStatusBO.getStatus() != null
                    && !Objects.equals(orderStatusBO.getStatus(), OrderStatus.CLOSE.value())
                    && !Objects.equals(orderStatusBO.getStatus(), OrderStatus.PAYED.value())
                    && !Objects.equals(orderStatusBO.getStatus(), OrderStatus.WAIT_GROUP.value())) {
                cancelOrderIds.add(orderStatusBO.getOrderId());
                orderType = orderStatusBO.getOrderType();
            }
        }
        // 取消订单之前，先查询下是否已支付成功
        ServerResponseEntity<List<Long>> paySuccessResponseEntity = paymentFeignClient.queryAndHandleOrderPaySuccess(new OrderPayInfoDTO(cancelOrderIds, ordersStatus.get(0).getUserId()));

        if (paySuccessResponseEntity.isFail()) {
            log.error("查询订单是否支付成功失败，订单id：{}，错误信息：{}", cancelOrderIds, paySuccessResponseEntity.getMsg());
            throw new LuckException(paySuccessResponseEntity.getMsg());
        }

        // 移除已支付成功的订单id
        cancelOrderIds.removeAll(paySuccessResponseEntity.getData());


        if (CollectionUtil.isEmpty(cancelOrderIds)) {
            log.info("订单已支付成功，不能取消，订单id：{}", orderIds);
            return;
        }
        int updateStatus = orderMapper.cancelOrders(cancelOrderIds);

        // 订单已经支付就不能取消了
        if (updateStatus == 0) {
            throw new LuckException("订单状态已发生改变，请刷新后再试");
        }
        // 团购订单
        if (Objects.equals(orderType, OrderType.GROUP.value())) {
            SendStatus groupSendStatus = groupOrderCancelMqTemplate.syncSend(RocketMqConstant.GROUP_ORDER_CANCEL_TOPIC, new GenericMessage<>(orderIds)).getSendStatus();
            if (!Objects.equals(groupSendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                log.error("团购订单取消失败，订单id：{}, 错误信息：{}", orderIds, groupSendStatus);
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }

        // 秒杀有自己的库存
        if (Objects.equals(orderType, OrderType.SECKILL.value())) {
            SendStatus groupSendStatus = seckillOrderCancelMqTemplate.syncSend(RocketMqConstant.SECKILL_ORDER_CANCEL_TOPIC, new GenericMessage<>(orderIds.get(0))).getSendStatus();
            if (!Objects.equals(groupSendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                log.error("秒杀订单取消失败，订单id：{}, 错误信息：{}", orderIds, groupSendStatus);
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        } else {
            // 解锁库存状态
            log.info("解锁库存，订单id：{}", orderIds);
            SendStatus stockSendStatus = stockMqTemplate.syncSend(RocketMqConstant.STOCK_UNLOCK_TOPIC, new GenericMessage<>(orderIds)).getSendStatus();
            if (!Objects.equals(stockSendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                log.error("库存解锁失败，订单id：{}, 错误信息：{}", orderIds, stockSendStatus);
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }

        if (Objects.equals(orderType, OrderType.ORDINARY.value())) {
            // 解锁优惠券状态
            log.info("解锁优惠券，订单id：{}", orderIds);
            SendStatus couponSendStatus = couponMqTemplate.syncSend(RocketMqConstant.COUPON_UNLOCK_TOPIC, new GenericMessage<>(orderIds)).getSendStatus();
            // 为什么不用批量消息，因为rocketmq不支持topic不一样发批量消息
            if (!Objects.equals(couponSendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                log.error("优惠券解锁失败，订单id：{}, 错误信息：{}", orderIds, couponSendStatus);
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
        if (Objects.equals(orderType, OrderType.ORDINARY.value()) || Objects.equals(orderType, OrderType.SCORE.value())) {
            // 解锁用户积分状态
            log.info("解锁用户积分，订单id：{}", orderIds);
            UserScoreBO userScoreBo = new UserScoreBO();
            userScoreBo.setUserId(ordersStatus.get(0).getUserId());
            userScoreBo.setOrderIds(orderIds);
            userScoreBo.setFlag(true);
            SendStatus userScoreSendStatus = userScoreTemplate.syncSend(RocketMqConstant.SCORE_UNLOCK_TOPIC, new GenericMessage<>(userScoreBo)).getSendStatus();
            if (!Objects.equals(userScoreSendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，发的出去无所谓
                log.error("用户积分解锁失败，订单id：{}, 用户id：{}", orderIds, ordersStatus.get(0).getUserId());
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }

        // todo 如果涉及到用户积分成长值之类的，要考虑下要不要分布式，取消的订单，除了支付成功，不然都不会改变订单状态
    }

    @Override
    public Order getOrderByOrderIdAndUserId(Long orderId, Long userId) {
        Order order = orderMapper.getOrderByOrderIdAndUserId(orderId, userId);
        if (order == null) {
            // 订单不存在
            throw new LuckException(ResponseEnum.ORDER_NOT_EXIST);
        }
        return order;
    }

    @Override
    public Order getOrderByOrderIdAndStationId(Long orderId, Long stationId) {
        Order order = orderMapper.getOrderByOrderIdAndStationId(orderId, stationId);
        if (order == null) {
            // 订单不存在
            log.error("订单不存在，订单id：{}", orderId);
            throw new LuckException(ResponseEnum.ORDER_NOT_EXIST);
        }
        return order;
    }

    @Override
    public OrderVO getOrderByOrderId(Long orderId) {
        Order order = orderMapper.getOrderByOrderIdAndShopId(orderId, AuthUserContext.get().getTenantId());
        if (order == null) {
            // 订单不存在
            log.error("订单不存在，订单id：{}", orderId);
            throw new LuckException(ResponseEnum.ORDER_NOT_EXIST);
        }
        return mapperFacade.map(order, OrderVO.class);
    }

    @Override
    public int receiptOrder(Long orderId) {
        return orderMapper.receiptOrder(orderId);
    }

    @Override
    public void deleteOrder(Long orderId) {
        orderMapper.deleteOrder(orderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void delivery(DeliveryOrderDTO deliveryOrderParam) {
        // 设置好收货人信息
        OrderAddr orderAddr = orderAddrService.getById(deliveryOrderParam.getOrderAddrId());
        OrderAddrVO orderAddrVO = mapperFacade.map(orderAddr, OrderAddrVO.class);
        if (Objects.nonNull(orderAddrVO)) {
            deliveryOrderParam.setConsignee(orderAddrVO.getConsignee());
            deliveryOrderParam.setMobile(orderAddrVO.getMobile());
        }
        deliveryOrderParam.setUserId(orderAddr.getUserId());
        Order orderDb = orderMapper.getDeliveryInfoByOrderId(deliveryOrderParam.getOrderId());
        // 订单不是待发货状态或者订单正在申请退款中，此时不能对订单进行发货操作
        if (!Objects.equals(orderDb.getStatus(), OrderStatus.PAYED.value()) || Objects.equals(orderDb.getRefundStatus(), RefundStatusEnum.APPLY.value())) {
            log.error("订单不是待发货状态或者订单正在申请退款中，此时不能对订单进行发货操作，订单id：{}", deliveryOrderParam.getOrderId());
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        orderItemService.updateByDeliveries(deliveryOrderParam.getSelectOrderItems(), deliveryOrderParam.getDeliveryType());
        // 算下未发货商品数量
        int unDeliveryNum = orderItemService.countUnDeliveryNumByOrderId(deliveryOrderParam.getOrderId());
        if (Objects.equals(deliveryOrderParam.getDeliveryType(), DeliveryType.DELIVERY.value())) {
            log.info("发货操作，推送给用户发货提醒，订单号为：{}，未发货商品数量为：{}", deliveryOrderParam.getOrderId(), unDeliveryNum);
            String companyName = deliveryCompanyFeignClient.getByDeliveryCompanyByCompanyId(deliveryOrderParam.getDeliveryCompanyId()).getData();
            StringBuilder sb = new StringBuilder();
            for (DeliveryOrderItemDTO selectOrderItem : deliveryOrderParam.getSelectOrderItems()) {
                sb.append(selectOrderItem.getSpuName()).append(StrUtil.COMMA);
            }
            sb.deleteCharAt(sb.length() - 1);
            // 获取订单发货信息
            // TODO 消息推送-发货提醒,通知其他服务
            SendNotifyBO sendNotifyBO = new SendNotifyBO();
            sendNotifyBO.setUserId(orderDb.getUserId());
            sendNotifyBO.setBizId(orderDb.getOrderId());
            sendNotifyBO.setSpuName(sb.toString());
            sendNotifyBO.setShopId(orderDb.getShopId());
            sendNotifyBO.setMobile(orderDb.getMobile());
            sendNotifyBO.setDvyName(companyName);
            sendNotifyBO.setSendType(SendTypeEnum.DELIVERY.getValue());
            sendNotifyBO.setDvyFlowId(deliveryOrderParam.getDeliveryNo());
            List<SendNotifyBO> sendNotifyList = Collections.singletonList(sendNotifyBO);
            SendStatus sendStockStatus = sendNotifyToUserTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_USER_TOPIC, new GenericMessage<>(sendNotifyList)).getSendStatus();
        }
        //修改为发货状态
        if (Objects.equals(unDeliveryNum, 0)) {
            log.info("订单已全部发货，订单号为：{}", deliveryOrderParam.getOrderId());
            Date date = new Date();
            Order order = new Order();
            order.setOrderId(deliveryOrderParam.getOrderId());
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setUpdateTime(date);
            order.setDeliveryTime(date);
            //判断是无需物流还是快递发货,如果是无需快递，则判断该订单是否包含有物流的项，若有物流则配送类型为快递配送，没有物流则不变
            if (orderItemService.getDevTypeByOrderId(deliveryOrderParam.getOrderId())) {
                order.setDeliveryType(DeliveryType.DELIVERY.value());
            } else {
                order.setDeliveryType(deliveryOrderParam.getDeliveryType());
            }
            orderMapper.update(order);
            // TODO 全部发货完成的消息通知
//            if(Objects.equals(order.getDvyType(), DeliveryType.DELIVERY.value())){
//                Delivery delivery = deliveryService.getById(deliveryOrder.getDeliveryCompanyId());
//                order.setDvyFlowId(deliveryOrder.getDeliveryNo());
//                dvyName = "";
//                if(delivery.getDvyName() != null){
//                    dvyName = delivery.getDvyName();
//                }
//            }
//            notifyTemplateService.sendNotifyOfDelivery(order,dvyName, SendType.DELIVERY);
        }

        // 确定订单发货后，保存订单包裹数据
        ServerResponseEntity<Void> deliveryResponseEntity = deliveryFeignClient.saveDeliveryInfo(deliveryOrderParam);
        if (deliveryResponseEntity.isFail()) {
            throw new LuckException(deliveryResponseEntity.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAmount(OrderAdminDTO orderAdminDTO, Order dbOrder) {
        if (!Objects.equals(dbOrder.getShopId(), AuthUserContext.get().getTenantId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (!Objects.equals(dbOrder.getStatus(), OrderStatus.UNPAY.value())) {
            throw new LuckException("订单状态已发生改变，无法更改订单金额");
        }
        //减少金额
        Long amount = 0L;
        //平台优惠金额
        Long platformAmount = 0L;
        Map<Long, OrderItemDTO> collect = orderAdminDTO.getOrderItems().stream().collect(Collectors.toMap(OrderItemDTO::getOrderItemId, orderItem -> orderItem));
        for (OrderItem orderItemDb : dbOrder.getOrderItems()) {
            orderItemDb.setSupplierId(dbOrder.getSupplierId());
            //判断是否是赠品订单项
            if (Objects.equals(orderItemDb.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                continue;
            }
            OrderItemDTO orderItem = collect.get(orderItemDb.getOrderItemId());
            boolean notChange = Objects.isNull(orderItem.getChangeAmount()) ||
                    Objects.equals(orderItem.getChangeAmount(), orderItemDb.getActualTotal()) ||
                    orderItemDb.getShopChangeFreeAmount() > 0;
            if (notChange) {
                continue;
            }
            if (orderItem.getChangeAmount() < Constant.MIN_ORDER_AMOUNT) {
                throw new LuckException("订单金额必须大于0");
            }
            Long changeAmount;
            // 改变金额大于订单金额-仅修改店铺改价优惠金额
            if (orderItem.getChangeAmount() > orderItemDb.getActualTotal()) {
                changeAmount = orderItem.getChangeAmount() - orderItemDb.getActualTotal();
                orderItemDb.setShopChangeFreeAmount(orderItemDb.getShopChangeFreeAmount() + changeAmount);
                //实际金额 = 原实际金额 - 变化金额
                orderItemDb.setActualTotal(orderItem.getChangeAmount());
                amount = amount + changeAmount;
                continue;
            }
            changeAmount = orderItemDb.getActualTotal() - orderItem.getChangeAmount();
            //修改平台优惠金额
            Long playformItemAmount = 0L;
            // 如果改变后金额小于当前金额，则进行修改平台优惠金额
            if (orderItem.getChangeAmount() < orderItemDb.getActualTotal() && orderItemDb.getPlatformShareReduce() > 0) {
                //金额减少比例 = 减少金额  % 总金额
                double proportion = Arith.div(changeAmount, orderItemDb.getSpuTotalAmount(), 6);
                //平台优惠金额减少金额 = 减少比例 * 原平台优惠金额
                playformItemAmount = Double.valueOf(Arith.round(Arith.mul(proportion, orderItemDb.getPlatformShareReduce()), 0)).longValue();
                //平台优惠金额 = 原平台优惠金额 - 平台优惠金额减少金额
                orderItemDb.setPlatformShareReduce(orderItemDb.getPlatformShareReduce() - playformItemAmount);
            }
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(orderItemDb.getActualTotal() - changeAmount);
            //总优惠金额 = 变化金额 + 原总优惠金额
            orderItemDb.setShareReduce(changeAmount + orderItemDb.getShareReduce());
            // 店铺改价金额为订单项减少的金额
            orderItemDb.setShopChangeFreeAmount(orderItemDb.getShopChangeFreeAmount() - changeAmount);
            amount = amount - changeAmount;
            platformAmount = platformAmount + playformItemAmount;
            // 优惠总额
            dbOrder.setReduceAmount(dbOrder.getReduceAmount() + changeAmount);
        }
        // 重新计算佣金
        calculatePlatformCommission(Collections.singletonList(dbOrder), dbOrder.getOrderItems());
        orderItemService.updateBatch(dbOrder.getOrderItems());
        OrderSettlement orderSettlement = orderSettlementService.getByOrderId(dbOrder.getOrderId());
        // 修改订单信息
        dbOrder.setActualTotal(dbOrder.getActualTotal() + amount);
        dbOrder.setPlatformAmount(dbOrder.getPlatformAmount() - platformAmount);
        // 计算运费变化金额
        calculTransFee(orderAdminDTO, dbOrder, amount);
        orderSettlement.setPayAmount(dbOrder.getActualTotal());
        orderSettlementService.update(orderSettlement);
        // 修改运费信息
        orderMapper.update(dbOrder);
    }

    private void calculTransFee(OrderAdminDTO orderAdminDTO, Order dbOrder, Long amount) {
        Long changeFreightAmount;
        Long freightAmount = orderAdminDTO.getFreightAmount() + dbOrder.getPlatformFreeFreightAmount();
        if (!Objects.equals(dbOrder.getFreightAmount(), freightAmount)) {
            ServerResponseEntity<Boolean> serverResponse = userLevelAndScoreOrderFeignClient.getHaveFreeFeeRight(dbOrder.getUserId(), dbOrder.getShopId());
            if (serverResponse.isFail()) {
                throw new LuckException(serverResponse.getMsg());
            }
            if (BooleanUtil.isTrue(serverResponse.getData())) {
                throw new LuckException("平台会员包邮不能修改运费");
            }
            if (orderAdminDTO.getFreightAmount() < 0L) {
                throw new LuckException("运费金额不能小于0");
            }
            changeFreightAmount = freightAmount - dbOrder.getFreightAmount();
            if (Objects.equals(dbOrder.getFreightAmount(), 0L) && dbOrder.getFreeFreightAmount() < 0L) {
                // 商家运费模板包邮，改价的运费由商家承担
                dbOrder.setFreeFreightAmount(-changeFreightAmount);
            } else if (dbOrder.getFreeFreightAmount() < 0L) {
                // 商家有商品运费模板包邮，改价的运费由不包邮商品承担
                dbOrder.setFreightAmount(freightAmount);
                if (changeFreightAmount < 0L) {
                    dbOrder.setFreeFreightAmount(dbOrder.getFreeFreightAmount() + changeFreightAmount);
                }
                dbOrder.setActualTotal(dbOrder.getActualTotal() + changeFreightAmount);
            } else {
                dbOrder.setFreightAmount(freightAmount);
                dbOrder.setActualTotal(dbOrder.getActualTotal() + changeFreightAmount);
            }
        }
        dbOrder.setShopChangeFreeAmount(dbOrder.getShopChangeFreeAmount() + amount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAmountByPreSale(OrderAdminDTO orderAdminDTO, Order dbOrder) {
        if (!Objects.equals(dbOrder.getShopId(), AuthUserContext.get().getTenantId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }
        if (!Objects.equals(dbOrder.getStatus(), OrderStatus.UNPAY.value())) {
            throw new LuckException("订单状态已发生改变，无法更改订单金额");
        }
        OrderPreSaleInfoVO orderPreSaleInfoVO = orderPreSaleInfoService.getByOrderId(dbOrder.getOrderId());
        //减少金额
        Long amount = 0L;
        //平台优惠金额
        Long platformAmount = 0L;
        Map<Long, OrderItemDTO> collect = orderAdminDTO.getOrderItems().stream().collect(Collectors.toMap(OrderItemDTO::getOrderItemId, orderItem -> orderItem));
        OrderItem orderItemDb = dbOrder.getOrderItems().get(0);
        orderItemDb.setSupplierId(dbOrder.getSupplierId());
        OrderItemDTO orderItem = collect.get(orderItemDb.getOrderItemId());
        boolean notChange = Objects.isNull(orderItem.getChangeAmount()) ||
                Objects.equals(orderItem.getChangeAmount(), orderItemDb.getActualTotal()) ||
                orderItemDb.getShopChangeFreeAmount() > 0;
        if (notChange) {
            return;
        }
        if (orderItem.getChangeAmount() < Constant.MIN_ORDER_AMOUNT && Objects.isNull(orderPreSaleInfoVO)) {
            throw new LuckException("订单金额必须大于0");
        }
        // 改变金额大于尾款金额-仅修改店铺改价优惠金额
        if (orderItem.getChangeAmount() > orderPreSaleInfoVO.getBalanceAmount()) {
            long changeBalanceAmount = orderItem.getChangeAmount() - orderPreSaleInfoVO.getBalanceAmount();
            orderItemDb.setShopChangeFreeAmount(orderItemDb.getShopChangeFreeAmount() + changeBalanceAmount);
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(orderItemDb.getActualTotal() + changeBalanceAmount);
            amount = amount + changeBalanceAmount;
        } else {
            long changeBalanceAmount = orderPreSaleInfoVO.getBalanceAmount() - orderItem.getChangeAmount();
            //修改平台优惠金额
            Long playformItemAmount = 0L;
            // 如果改变后金额小于当前金额，则进行修改平台优惠金额
            if (orderItemDb.getPlatformShareReduce() > 0) {
                //金额减少比例 = 减少金额  % 总金额
                double proportion = Arith.div(changeBalanceAmount, orderItemDb.getSpuTotalAmount(), 6);
                //平台优惠金额减少金额 = 减少比例 * 原平台优惠金额
                playformItemAmount = Double.valueOf(Arith.round(Arith.mul(proportion, orderItemDb.getPlatformShareReduce()), 0)).longValue();
                //平台优惠金额 = 原平台优惠金额 - 平台优惠金额减少金额
                orderItemDb.setPlatformShareReduce(orderItemDb.getPlatformShareReduce() - playformItemAmount);
            }
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(orderItemDb.getActualTotal() - changeBalanceAmount);
            //总优惠金额 = 变化金额 + 原总优惠金额
            orderItemDb.setShareReduce(changeBalanceAmount + orderItemDb.getShareReduce());
            // 店铺改价金额为订单项减少的金额
            orderItemDb.setShopChangeFreeAmount(orderItemDb.getShopChangeFreeAmount() - changeBalanceAmount);
            amount = amount - changeBalanceAmount;
            platformAmount = platformAmount + playformItemAmount;
            // 优惠总额
            dbOrder.setReduceAmount(dbOrder.getReduceAmount() + changeBalanceAmount);
        }
        // 修改预售信息
        orderPreSaleInfoVO.setBalanceAmount(orderItem.getChangeAmount());
        OrderPreSaleInfo orderPreSaleInfo = mapperFacade.map(orderPreSaleInfoVO, OrderPreSaleInfo.class);
        orderPreSaleInfoService.updateBatch(Collections.singletonList(orderPreSaleInfo));
        //---------for------
        // 重新计算佣金
        calculatePlatformCommission(Collections.singletonList(dbOrder), dbOrder.getOrderItems());
        orderItemService.updateBatch(dbOrder.getOrderItems());
        OrderSettlement orderSettlement = orderSettlementService.getByOrderId(dbOrder.getOrderId());
        // 修改订单信息
        dbOrder.setActualTotal(dbOrder.getActualTotal() + amount);
        dbOrder.setPlatformAmount(dbOrder.getPlatformAmount() - platformAmount);
        // 计算运费变化金额
        calculTransFee(orderAdminDTO, dbOrder, amount);
        orderSettlement.setPayAmount(dbOrder.getActualTotal());
        orderSettlementService.update(orderSettlement);
        // 修改运费信息
        orderMapper.update(dbOrder);
    }

    @Override
    public SubmitOrderPayAmountInfoBO getSubmitOrderPayAmountInfo(long[] orderIdList) {
        if (ArrayUtil.isEmpty(orderIdList)) {
            return null;
        }
        return orderMapper.getSubmitOrderPayAmountInfo(orderIdList);
    }

    @Override
    public EsOrderBO getEsOrder(Long orderId) {
        return orderMapper.getEsOrder(orderId);
    }


    private OrderItem getOrderItem(ShopCartOrderMergerVO mergerOrder, Order order, ShopCartItemVO shopCartItem, Map<Long, List<VirtualRemarkVO>> virtualRemarkMap, ShopCartOrderVO shopCartOrderVO) {
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderItemId(shopCartItem.getOrderItemId());
        orderItem.setOrderId(order.getOrderId());
        orderItem.setShopId(shopCartItem.getShopId());
        orderItem.setSkuId(shopCartItem.getSkuId());
        orderItem.setSpuId(shopCartItem.getSpuId());
        orderItem.setCategoryId(shopCartItem.getCategoryId());
        // TODO 国际化
        orderItem.setOrderItemLangList(getOrderItemLangList(shopCartItem));
        orderItem.setCount(shopCartItem.getCount());
        // 待发货数量
        orderItem.setBeDeliveredNum(shopCartItem.getCount());
        orderItem.setPic(shopCartItem.getImgUrl());
        orderItem.setPrice(shopCartItem.getSkuPriceFee());
        orderItem.setUserId(order.getUserId());
        orderItem.setSpuTotalAmount(shopCartItem.getTotalAmount());
        orderItem.setIsComm(0);
        orderItem.setShopCartTime(shopCartItem.getCreateTime());
        // 分销金额
        orderItem.setDistributionAmount(0L);
        orderItem.setDistributionParentAmount(0L);
        //平台的补贴优惠金额
        orderItem.setPlatformShareReduce(shopCartItem.getPlatformShareReduce());
        // 实际订单项支付金额
        orderItem.setActualTotal(shopCartItem.getActualTotal());
        // 分摊优惠金额
        orderItem.setShareReduce(shopCartItem.getShareReduce());
        //推广员卡号
        orderItem.setDistributionUserId(shopCartItem.getDistributionUserId());
        // 积分价格（单价）
        orderItem.setScoreFee(shopCartItem.getScoreFee());
        //使用积分价格
        orderItem.setUseScore(shopCartItem.getScorePrice() != null ? shopCartItem.getScorePrice() : 0L);
        orderItem.setScoreAmount(shopCartItem.getScoreReduce() != null ? shopCartItem.getScoreReduce() : 0L);
        orderItem.setMemberAmount(shopCartItem.getLevelReduce() != null ? shopCartItem.getLevelReduce() : 0L);

        orderItem.setPlatformCouponAmount(shopCartItem.getPlatformCouponAmount() != null ? shopCartItem.getPlatformCouponAmount() : 0L);
        orderItem.setShopCouponAmount(shopCartItem.getShopCouponAmount() != null ? shopCartItem.getShopCouponAmount() : 0L);
        orderItem.setDiscountAmount(shopCartItem.getDiscountAmount() != null ? shopCartItem.getDiscountAmount() : 0L);
        orderItem.setPlatformFreeFreightAmount(shopCartItem.getPlatformFreeFreightAmount() != null ? shopCartItem.getPlatformFreeFreightAmount() : 0L);
        // 平台佣金
        orderItem.setRate(shopCartItem.getRate() != null ? shopCartItem.getRate() : 0.0);
        orderItem.setPlatformCommission(shopCartItem.getPlatformCommission() != null ? shopCartItem.getPlatformCommission() : 0L);
        orderItem.setSupplierRate(Objects.nonNull(shopCartItem.getSupplierRate()) ? shopCartItem.getSupplierRate() : 0.0);
        orderItem.setPurchasePlatformCommission(Objects.nonNull(shopCartItem.getPurchasePlatformCommission()) ? shopCartItem.getPurchasePlatformCommission() : 0L);

        // 获取积分，确认收货之后才会获取积分
        orderItem.setGainScore(0L);
        // 生成订单之后才会进行订单改价
        orderItem.setShopChangeFreeAmount(0L);
        // 改价之后才会商家免运费，注意：要是改变了规则，这里也要改
        orderItem.setFreeFreightAmount(0L);
        orderItem.setSpuMold(SpuMold.REAL.value());
        // 如果是虚拟商品，则修改为无需快递的发货方式
        if (Objects.equals(shopCartItem.getSpuMold(), 1)) {
            // 存入留言
            String virtualRemarkStr = Json.toJsonString(virtualRemarkMap.get(shopCartItem.getSpuId()));
            orderItem.setVirtualRemark(virtualRemarkStr);
            orderItem.setSpuMold(SpuMold.VIRTUAL.value());
            orderItem.setIsRefund(shopCartItem.getIsRefund());
            orderItem.setDeliveryType(DeliveryType.NOT_DELIVERY.value());
            SpuVO spuVO = spuFeignClient.getDetailById(shopCartItem.getSpuId()).getData();
            if (Objects.nonNull(spuVO)) {
                shopCartOrderVO.setWriteOffNum(spuVO.getWriteOffNum());
                shopCartOrderVO.setIsRefund(spuVO.getIsRefund());
                // 如果是虚拟商品且需要核销，放进去
                if (!Objects.equals(spuVO.getWriteOffNum(), 0) && !Objects.equals(spuVO.getWriteOffNum(), null)) {
                    Date startTime = new Date();
                    Date endTime;
                    // 判断有效期
                    switch (spuVO.getWriteOffTime()) {
                        case -1:
                            endTime = null;
                            break;
                        case 0:
                            startTime = spuVO.getWriteOffStart();
                            endTime = spuVO.getWriteOffEnd();
                            break;
                        case 1:
                            endTime = DateUtil.endOfDay(startTime);
                            break;
                        default:
                            endTime = DateUtil.offsetDay(startTime, spuVO.getWriteOffTime());
                            break;
                    }
                    shopCartOrderVO.setWriteOffStart(startTime);
                    shopCartOrderVO.setWriteOffEnd(endTime);
                    if (Objects.equals(spuVO.getWriteOffNum(), -1)) {
                        shopCartOrderVO.setWriteOffMultipleCount(spuVO.getWriteOffMultipleCount());
                    }
                }
            }
        }
        // 供应商相关信息保存
        orderItem.setItemPurchaseAmount(shopCartItem.getTotalPurchaseAmount() != null ? shopCartItem.getTotalPurchaseAmount() : 0L);
        orderItem.setSupplierId(shopCartItem.getSupplierId());
        orderItem.setSpuCode(shopCartItem.getSpuCode());
        orderItem.setPartyCode(shopCartItem.getPartyCode());
        orderItem.setSupplierSkuId(shopCartItem.getSupplierSkuId());
        orderItem.setSupplierSpuId(shopCartItem.getSupplierSpuId());
        orderItem.setComboAmount(shopCartItem.getComboAmount());
//        GiveawayVO giveaway = shopCartItem.getGiveaway();
//        if (Objects.nonNull(giveaway)) {
//            orderItem.setActivityId(0L);
//            orderItem.setActivityType(OrderActivityType.GIVEAWAY.value());
//        }
        orderItem.setGiveawayAmount(0L);

        if (Objects.nonNull(shopCartItem.getComboId())) {
            orderItem.setActivityId(shopCartItem.getComboId());
            orderItem.setActivityType(OrderActivityType.COMBO.value());
        }

        if (Objects.equals(mergerOrder.getActivityType(), OrderActivityType.GROUP.value()) ||
                Objects.equals(mergerOrder.getActivityType(), OrderActivityType.SECKILL.value())) {
            orderItem.setActivityId(mergerOrder.getActivityId());
            orderItem.setActivityType(mergerOrder.getActivityType());
        }
//        //供应商订单字段数据
//        if(Objects.nonNull(shopCartItem.getSupplierSpuId())){
//            SpuVO supplierSpuVO = spuFeignClient.getSpuAndSkuBySpuId(shopCartItem.getSupplierSpuId()).getData();
//            Map<Long, SkuVO> supplierSkuVOMap = supplierSpuVO.getSkus().stream().collect(Collectors.toMap(SkuVO::getSkuId, s -> s));
//            orderItem.setSupplierSpuName(supplierSpuVO.getName());
//            SkuVO supplierSkuVO = supplierSkuVOMap.get(shopCartItem.getSupplierSkuId());
//            orderItem.setSupplierPic(supplierSkuVO.getImgUrl() == null ? supplierSkuVO.getMainImgUrl() : supplierSkuVO.getImgUrl());
//        }
        return orderItem;
    }

    private List<OrderItem> giveawayOrderItems(Order order, ShopCartItemVO shopCartItem) {
        int allCount = order.getAllCount();
        List<OrderItem> orderItemList = new ArrayList<>();
        GiveawayVO giveaway = shopCartItem.getGiveaway();
        if (Objects.isNull(giveaway)) {
            return orderItemList;
        }
//        order.getOrderItems().get(0).setOrderItemId(segmentFeignClient.getSegmentIdWithDateTime(DistributedIdKey.MALL4CLOUD_ORDER, order.getUserId()).getData());
        for (GiveawaySpuVO giveawaySpuVO : giveaway.getGiveawaySpus()) {
            OrderItem orderItem = new OrderItem();
            orderItem.setShopId(order.getShopId());
            // TODO 国际化
            ShopCartItemVO shopCartItemVO = shopCartItem;
            if (giveawaySpuVO.getSpuName() != null) {
                List<OrderSpuLangVO> spuLangList = new ArrayList<>();
                OrderSpuLangVO orderSpuLangVO = new OrderSpuLangVO();
                orderSpuLangVO.setLang(I18nMessage.getLang());
                orderSpuLangVO.setSpuName(giveawaySpuVO.getSpuName());
                spuLangList.add(orderSpuLangVO);
                shopCartItemVO.setSpuLangList(spuLangList);
            }
            if (giveawaySpuVO.getSkuName() != null) {
                List<OrderSkuLangVO> skuLangList = new ArrayList<>();
                OrderSkuLangVO orderSkuLangVO = new OrderSkuLangVO();
                orderSkuLangVO.setLang(I18nMessage.getLang());
                orderSkuLangVO.setSkuName(giveawaySpuVO.getSkuName());
                skuLangList.add(orderSkuLangVO);
                shopCartItemVO.setSkuLangList(skuLangList);
            }
            orderItem.setOrderItemLangList(getOrderItemLangList(shopCartItemVO));
            orderItem.setCategoryId(giveawaySpuVO.getCategoryId());
            orderItem.setOrderId(order.getOrderId());
            orderItem.setSpuId(giveawaySpuVO.getSpuId());
            orderItem.setSkuId(giveawaySpuVO.getSkuId());
            //orderItem.setSkuName(giveawaySpuVO.getSkuName());
            SpuVO spuVO = spuFeignClient.getById(giveawaySpuVO.getSpuId()).getData();
            SkuVO skuVO = skuFeignClient.getById(giveawaySpuVO.getSkuId()).getData();
            orderItem.setPic(StrUtil.isBlank(skuVO.getImgUrl()) ? spuVO.getMainImgUrl() : skuVO.getImgUrl());
            // 保存中英文名称
            //orderItem.setSpuName(giveawaySpuVO.getSpuName());
            int spuCount = giveawaySpuVO.getGiveawayNum();
            allCount = allCount + spuCount;
            orderItem.setCount(spuCount);
            //代发货数量
            orderItem.setBeDeliveredNum(spuCount);
            orderItem.setPrice(giveawaySpuVO.getPriceFee());
            orderItem.setUserId(order.getUserId());
            orderItem.setSpuTotalAmount(giveawaySpuVO.getPriceFee());
            orderItem.setIsComm(0);
            //平台的补贴优惠金额
            orderItem.setPlatformShareReduce(Constant.ZERO_LONG);
            // 实际订单项支付金额
            orderItem.setActualTotal(Constant.ZERO_LONG);
            // 分摊优惠金额
            orderItem.setShareReduce(Constant.ZERO_LONG);
            orderItem.setMemberAmount(Constant.ZERO_LONG);
            orderItem.setScoreAmount(Constant.ZERO_LONG);
            orderItem.setDistributionAmount(Constant.ZERO_LONG);
            orderItem.setDistributionParentAmount(Constant.ZERO_LONG);
            orderItem.setPlatformCouponAmount(Constant.ZERO_LONG);
            orderItem.setShopCouponAmount(Constant.ZERO_LONG);
            orderItem.setDiscountAmount(Constant.ZERO_LONG);
            orderItem.setPlatformFreeFreightAmount(Constant.ZERO_LONG);
            // 平台佣金
            orderItem.setRate(shopCartItem.getRate() != null ? shopCartItem.getRate() : 0.0);
            orderItem.setPlatformCommission(Constant.ZERO_LONG);
            orderItem.setSupplierRate(Objects.nonNull(shopCartItem.getSupplierRate()) ? shopCartItem.getSupplierRate() : 0.0);
            orderItem.setPurchasePlatformCommission(Constant.ZERO_LONG);
            //使用积分价格
            orderItem.setUseScore(Constant.ZERO_LONG);
            // 改价之后才会商家免运费，注意：要是改变了规则，这里也要改
            orderItem.setFreeFreightAmount(Constant.ZERO_LONG);
            // 获取积分，确认收货之后才会获取积分
            orderItem.setGainScore(Constant.ZERO_LONG);
            // 生成订单之后才会进行订单改价
            orderItem.setShopChangeFreeAmount(Constant.ZERO_LONG);
            // 供应商相关信息保存
            orderItem.setItemPurchaseAmount(Constant.ZERO_LONG);
            orderItem.setSupplierId(shopCartItem.getSupplierId());
            orderItem.setSpuCode(shopCartItem.getSpuCode());
            orderItem.setPartyCode(shopCartItem.getPartyCode());
            orderItem.setSupplierSkuId(shopCartItem.getSupplierSkuId());
            orderItem.setSupplierSpuId(shopCartItem.getSupplierSpuId());
            // 赠品
            orderItem.setGiveawayAmount((long) Arith.mul(giveawaySpuVO.getRefundPrice(), spuCount));
            orderItem.setMainGiveaway(0);
            orderItem.setActivityId(shopCartItem.getOrderItemId());
            orderItem.setActivityType(OrderActivityType.GIVEAWAY.value());
            orderItemList.add(orderItem);
        }
        order.setAllCount(allCount);

        if (CollUtil.isEmpty(orderItemList)) {
            return orderItemList;
        }

        // 获取赠品订单项id
        ServerResponseEntity<Map<String, List<Long>>> serverResponseEntity = segmentFeignClient.batchSegmentIdWithDateTime(new SegmentDTO(order.getUserId(), DistributedIdKey.MALL4CLOUD_ORDER_ITEM, orderItemList.size()));
        if (serverResponseEntity.isFail()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }
        List<Long> orderItemIds = serverResponseEntity.getData().get(DistributedIdKey.MALL4CLOUD_ORDER_ITEM);
        for (OrderItem orderItem : orderItemList) {
            orderItem.setOrderItemId(orderItemIds.remove(0));
        }
        return orderItemList;
    }


    private OrderPreSaleInfo getOrderPresaleInfo(Order order, ShopCartItemVO shopCartItem) {
        OrderPreSaleInfo orderPreSaleInfo = new OrderPreSaleInfo();
        orderPreSaleInfo.setOrderId(order.getOrderId());
        orderPreSaleInfo.setPreSaleType(shopCartItem.getPreSaleType());
        // 如果是定金预售，保存下定金信息，否则只保存发货信息
        if (Objects.equals(shopCartItem.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            orderPreSaleInfo.setDepositAmount(shopCartItem.getActualDepositAmount());
            orderPreSaleInfo.setDepositExpansionAmount(shopCartItem.getDepositExpansionAmount());
            orderPreSaleInfo.setDepositReduceAmount(shopCartItem.getDepositReduceAmount());
            orderPreSaleInfo.setBalanceAmount(shopCartItem.getActualBalanceAmount());
            orderPreSaleInfo.setBalanceStartTime(shopCartItem.getBalanceStartTime());
            orderPreSaleInfo.setBalanceEndTime(shopCartItem.getBalanceEndTime());
            orderPreSaleInfo.setUserId(order.getUserId());
        }
        orderPreSaleInfo.setPreSaleDeliveryTime(shopCartItem.getPreSaleDeliveryTime());
        orderPreSaleInfo.setPreSaleDeliveryType(shopCartItem.getPreSaleDeliveryType());
        // 供应商相关信息保存
        return orderPreSaleInfo;
    }

    /**
     * 获取订单项的国际化信息
     *
     * @param shopCartItem 购物车项
     * @return 订单项的国际化信息列表
     */
    private List<OrderItemLang> getOrderItemLangList(ShopCartItemVO shopCartItem) {
        List<OrderItemLang> orderItemLangList = new ArrayList<>();
        Map<Integer, String> spuNameMap = shopCartItem.getSpuLangList().stream()
                .filter(orderSpuLangVO -> StrUtil.isNotBlank(orderSpuLangVO.getSpuName()))
                .collect(Collectors.toMap(OrderSpuLangVO::getLang, OrderSpuLangVO::getSpuName));
        Map<Integer, String> skuNameMap = shopCartItem.getSkuLangList().stream()
                .filter(orderSkuLangVO -> StrUtil.isNotBlank(orderSkuLangVO.getSkuName()))
                .collect(Collectors.toMap(OrderSkuLangVO::getLang, OrderSkuLangVO::getSkuName));

        for (LanguageEnum value : LanguageEnum.values()) {
            Integer lang = value.getLang();
            if (!spuNameMap.containsKey(lang) && !skuNameMap.containsKey(lang)) {
                continue;
            }
            OrderItemLang orderItemLang = new OrderItemLang();
            orderItemLang.setLang(value.getLang());
            orderItemLang.setSkuName(LangUtil.getLangValue(skuNameMap, lang));
            orderItemLang.setSpuName(LangUtil.getLangValue(spuNameMap, lang));
            orderItemLangList.add(orderItemLang);
        }
        return orderItemLangList;
    }

    private Order getOrder(Long userId, Integer dvyType, Integer spuMold, ShopCartOrderVO shopCartOrderVO) {
        if (Objects.nonNull(shopCartOrderVO.getIsHaveComboOrder()) && shopCartOrderVO.getIsHaveComboOrder()) {
            spuMold = shopCartOrderVO.getSpuMold();
        }else {
            spuMold = Objects.isNull(shopCartOrderVO.getSpuMold()) ? spuMold : shopCartOrderVO.getSpuMold();
        }
        dvyType = Objects.equals(spuMold, 1) ? DeliveryType.NOT_DELIVERY.value() : dvyType;
        // 订单信息
        Order order = new Order();
        order.setOrderId(shopCartOrderVO.getOrderId());

        order.setShopId(shopCartOrderVO.getShopId());
        order.setShopName(shopCartOrderVO.getShopName());
        // 用户id
        order.setUserId(userId);
        // 商品总额
        order.setTotal(shopCartOrderVO.getTotal());
        // 实际总额
        order.setActualTotal(shopCartOrderVO.getActualTotal());
        order.setStatus(OrderStatus.UNPAY.value());
        order.setIsPayed(0);
        order.setDeleteStatus(0);
        order.setAllCount(shopCartOrderVO.getTotalCount());
        order.setReduceAmount(shopCartOrderVO.getShopReduce());
        order.setFreightAmount(shopCartOrderVO.getTransfee());
        order.setRemarks(shopCartOrderVO.getRemarks());
        order.setDeliveryType(dvyType);
        order.setOrderScore(shopCartOrderVO.getUseScore());
        order.setOrderType(shopCartOrderVO.getOrderType() != null ? shopCartOrderVO.getOrderType() : OrderType.ORDINARY.value());
        order.setPlatformAmount(shopCartOrderVO.getPlatformAmount() != null ? shopCartOrderVO.getPlatformAmount() : 0L);
        order.setScoreAmount(shopCartOrderVO.getScoreReduce() != null ? shopCartOrderVO.getScoreReduce() : 0L);
        order.setMemberAmount(shopCartOrderVO.getLevelReduce() != null ? shopCartOrderVO.getLevelReduce() : 0L);
        order.setPlatformCouponAmount(shopCartOrderVO.getPlatformCouponReduce() != null ? shopCartOrderVO.getPlatformCouponReduce() : 0L);
        order.setShopCouponAmount(shopCartOrderVO.getCouponReduce() != null ? shopCartOrderVO.getCouponReduce() : 0L);
        order.setDiscountAmount(shopCartOrderVO.getDiscountReduce() != null ? shopCartOrderVO.getDiscountReduce() : 0L);
        order.setPlatformAmount(shopCartOrderVO.getPlatformAmount() != null ? shopCartOrderVO.getPlatformAmount() : 0L);
        order.setReduceAmount(shopCartOrderVO.getShopReduce() != null ? shopCartOrderVO.getShopReduce() : 0L);
        order.setFreeFreightAmount(shopCartOrderVO.getFreeTransfee() != null ? shopCartOrderVO.getFreeTransfee() : 0L);
        order.setPlatformFreeFreightAmount(shopCartOrderVO.getLevelFreeTransfee() != null ? shopCartOrderVO.getLevelFreeTransfee() : 0L);
        order.setPlatformCommission(shopCartOrderVO.getPlatformCommission() != null ? shopCartOrderVO.getPlatformCommission() : 0L);
        order.setDistributionAmount(0L);
        order.setShopChangeFreeAmount(0L);
        order.setIsSettled(0);
        order.setSupplierId(0L);
        order.setSupplierDeliveryType(0);
        order.setWaitPurchase(0);
        order.setPurchaseSpreadAmount(0L);
        order.setPreSaleType(shopCartOrderVO.getPreSaleType());
        order.setOrderMold(spuMold);
        order.setShopComboAmount(calculateShopComboAmount(shopCartOrderVO));
        // 供应商相关
        // 判断下是否为供应商商品,如果是商家代销供应商商品且为供应商发货设置供应商信息
        if (!Objects.equals(shopCartOrderVO.getSupplierId(), 0L) && Objects.equals(shopCartOrderVO.getSupplierDeliveryType(), 1)) {
            order.setSupplierId(shopCartOrderVO.getSupplierId());
            order.setSupplierDeliveryType(shopCartOrderVO.getSupplierDeliveryType());
        }
        return order;
    }

    /**
     * 计算订单套餐商品优惠金额
     *
     * @param shopCartOrderVO
     * @return
     */
    private Long calculateShopComboAmount(ShopCartOrderVO shopCartOrderVO) {
        List<ShopCartItemDiscountVO> shopCartItemDiscounts = shopCartOrderVO.getShopCartItemDiscounts();
        Long shopComboAmount = 0L;
        for (ShopCartItemDiscountVO shopCartItemDiscount : shopCartItemDiscounts) {
            List<ShopCartItemVO> shopCartItems = shopCartItemDiscount.getShopCartItems();
            for (ShopCartItemVO shopCartItem : shopCartItems) {
                if (Objects.nonNull(shopCartItem.getComboId()) && shopCartItem.getComboId() > 0) {
                    shopComboAmount += shopCartItem.getComboAmount();
                }
            }
        }
        return shopComboAmount;
    }

    @Override
    public Long sumTotalDistributionAmountByOrderItem(List<OrderItem> orderItems) {
        // 订单总分销金额
        long totalDistributionAmount = 0L;
        if (CollectionUtil.isNotEmpty(orderItems)) {
            for (OrderItem orderItem : orderItems) {
                if (Objects.isNull(orderItem.getDistributionUserId())) {
                    continue;
                }
                // 如果改订单项已经退款了的话，分销员的佣金就已经回退了，不需要继续算钱
                if (Objects.equals(orderItem.getRefundStatus(), RefundStatusEnum.SUCCEED.value())) {
                    continue;
                }
                // 分销佣金
                if (orderItem.getDistributionAmount() != null && orderItem.getDistributionAmount() > 0) {
                    totalDistributionAmount = totalDistributionAmount + orderItem.getDistributionAmount();
                }
                // 上级分销佣金
                if (orderItem.getDistributionParentAmount() != null && orderItem.getDistributionParentAmount() > 0) {
                    totalDistributionAmount = totalDistributionAmount + orderItem.getDistributionParentAmount();
                }
            }
        }
        return totalDistributionAmount;
    }

    @Override
    public Order getOrderAndOrderItemData(Long orderId, Long shopId) {
        Order order = orderMapper.getOrderAndOrderItemData(orderId, shopId);
        orderLangHandle(order);
        return order;
    }

    @Override
    public Order getSupOrderAndOrderItemData(Long orderId, Long supplierId) {
        Order order = orderMapper.getSupOrderAndOrderItemData(orderId, supplierId);
        orderLangHandle(order);
        return order;
    }

    @Override
    public OrderCountVO countNumberOfStatus(Long userId) {
        return orderMapper.countNumberOfStatus(userId);
    }

    @Override
    public EsPageVO<EsOrderVO> myOrderPage(OrderSearchDTO orderSearchDTO) {
        if (StrUtil.isBlank(orderSearchDTO.getSpuName())) {
            PageDTO pageDTO = new PageDTO();
            pageDTO.setPageNum(orderSearchDTO.getPageNum());
            pageDTO.setPageSize(orderSearchDTO.getPageSize());
            PageVO<Long> pageVO = PageUtil.doPage(pageDTO, () -> orderMapper.getPageOrderIds(orderSearchDTO));
            EsPageVO page = new EsPageVO();
            page.setTotal(pageVO.getTotal());
            page.setPages(pageVO.getPages());
            if (CollUtil.isNotEmpty(pageVO.getList())) {
                List<EsOrderVO> orderList = orderMapper.userOrderList(pageVO.getList(), I18nMessage.getLang());
                OrderLangUtil.esOrderVOLang(orderList);
                page.setList(orderList);
            } else {
                page.setList(new ArrayList());
            }
            return page;
        }
        return orderPage(orderSearchDTO);
    }

    @Override
    public EsPageVO<EsOrderVO> orderPage(OrderSearchDTO orderSearchDTO) {

        // 处理下payType
        List<Integer> payTypeList = new ArrayList<>();
        if (Objects.equals(orderSearchDTO.getPayType(), SearchPayType.WECHATPAY.value())) {
            payTypeList.addAll(Arrays.asList(PayType.weChatPayArray));
        } else if (Objects.equals(orderSearchDTO.getPayType(), SearchPayType.ALIPAY.value())) {
            payTypeList.addAll(Arrays.asList(PayType.aliPayArray));
        } else if (Objects.equals(orderSearchDTO.getPayType(), SearchPayType.BALANCE.value())) {
            payTypeList.add(PayType.BALANCE.value());
        } else if (Objects.equals(orderSearchDTO.getPayType(), SearchPayType.SCOREPAY.value())) {
            payTypeList.add(PayType.SCOREPAY.value());
        }
        orderSearchDTO.setPayTypeList(payTypeList);
        ServerResponseEntity<EsPageVO<EsOrderVO>> orderResponse = searchOrderFeignClient.pageOrder(orderSearchDTO);
        return orderResponse.getData();
    }

    @Override
    public int countByOrderId(Long orderId) {
        return orderMapper.countByOrderId(orderId);
    }


    @Override
    public EsPageVO<EsOrderVO> pageByUserId(PageDTO pageDTO, String userId) {
        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        orderSearchDTO.setUserId(Long.valueOf(userId));
        orderSearchDTO.setPageNum(pageDTO.getPageNum());
        orderSearchDTO.setPageSize(pageDTO.getPageSize());
        orderSearchDTO.setShopId(AuthUserContext.get().getTenantId());
        ServerResponseEntity<EsPageVO<EsOrderVO>> orderResponseEntity = searchOrderFeignClient.pageOrder(orderSearchDTO);
        if (orderResponseEntity.isFail()) {
            log.info("查询订单列表失败，失败原因：{}", orderResponseEntity.getMsg());
            throw new LuckException(orderResponseEntity.getMsg());
        }
        return orderResponseEntity.getData();
    }


    @Override
    public int settledOrder(List<Long> orderIds) {
        return orderMapper.settledOrder(orderIds);
    }

    @Override
    public EsOrderBO saveMongoAndGetEsInfo(Long orderId) {
        MongoOrderBO order = orderMapper.getMongodbOrderInfo(orderId);
        MongoOrderBO mongoOrderBO = loadMongoOrderBo(order);
        mongoOrderManager.save(mongoOrderBO);
        return mapperFacade.map(mongoOrderBO, EsOrderBO.class);
    }

    private MongoOrderBO loadMongoOrderBo(MongoOrderBO orderBO) {
        // 拼接字符串
        StringBuilder spuCodes = new StringBuilder(500);
        StringBuilder partyCodes = new StringBuilder(500);
        List<Long> spuIds = new ArrayList<>(10);
        for (MongoOrderItemBO orderItem : orderBO.getOrderItems()) {
            spuIds.add(orderItem.getSpuId());
            for (OrderItemLangVO orderItemLang : orderItem.getOrderItemLangList()) {
                if (Objects.equals(orderItemLang.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                    orderItem.setSpuNameZh(orderItemLang.getSpuName());
                    orderItem.setSkuNameZh(orderItemLang.getSkuName());
                } else if (Objects.equals(orderItemLang.getLang(), LanguageEnum.LANGUAGE_EN.getLang())) {
                    orderItem.setSpuNameEn(orderItemLang.getSpuName());
                    orderItem.setSkuNameEn(orderItemLang.getSkuName());
                }
            }
            if (StrUtil.isNotBlank(orderItem.getSpuCode())) {
                spuCodes.append(orderItem.getSpuCode()).append(StrUtil.COMMA);
            }
            if (StrUtil.isNotBlank(orderItem.getPartyCode())) {
                partyCodes.append(orderItem.getPartyCode()).append(StrUtil.COMMA);
            }
        }
        setPrimaryCategoryId(orderBO, spuIds);
        setShopAddr(orderBO);
        // 判断是否为新成交用户
        MongoOrderBO firstOrderData = orderMapper.getUserFirstUserOrder(orderBO.getUserId(), orderBO.getSupplierId(), orderBO.getOrderId());
        orderBO.setFirstOrder(firstOrderData.getFirstOrder());
        orderBO.setFirstSupplierOrder(firstOrderData.getFirstSupplierOrder());

        // 插入会员类型
        ServerResponseEntity<Integer> userTypeEntity = userLevelLogClient.getUserTypeAtTime(new UserTypeDTO(orderBO.getUserId(), orderBO.getCreateTime()));
        if (userTypeEntity.isFail()) {
            throw new LuckException(userTypeEntity.getMsg());
        }
        orderBO.setUserType(userTypeEntity.getData());
        if (spuCodes.length() > 1 && spuCodes.lastIndexOf(StrUtil.COMMA) == spuCodes.length() - 1) {
            spuCodes.deleteCharAt(spuCodes.length() - 1);
        }

        if (partyCodes.length() > 1 && partyCodes.lastIndexOf(StrUtil.COMMA) == partyCodes.length() - 1) {
            partyCodes.deleteCharAt(partyCodes.length() - 1);
        }
        orderBO.setSpuCodes(spuCodes.toString());
        orderBO.setPartyCodes(partyCodes.toString());
        return orderBO;
    }

    private void  setShopAddr(MongoOrderBO orderBO){
        ShopDetailVO shopDetailVO=shopDetailFeignClient.getShopDetailByShopId(orderBO.getShopId()).getData();
        if(null != shopDetailVO){
            orderBO.setShopAddr(shopDetailVO.getArea());
            orderBO.setShopAddrId(shopDetailVO.getAreaId());
        }

    }

    private void setPrimaryCategoryId(MongoOrderBO orderBO, List<Long> spuIds) {
        ProductSearchDTO productSearchDTO = new ProductSearchDTO();
        productSearchDTO.setPageSize(PageDTO.MAX_PAGE_SIZE);
        productSearchDTO.setPageNum(PageDTO.DEFAULT_PAGE_NUM);
        productSearchDTO.setSpuIds(spuIds);
        ServerResponseEntity<EsPageVO<SpuAdminVO>> searchResponse = searchSpuFeignClient.adminPage(productSearchDTO);
        if (searchResponse.isFail()) {
            throw new LuckException(searchResponse.getMsg());
        }
        List<SpuAdminVO> spuList = searchResponse.getData().getList();
        if (CollUtil.isNotEmpty(spuList)) {
            Map<Long, Long> categoryMap = spuList.stream().collect(Collectors.toMap(SpuAdminVO::getSpuId, SpuAdminVO::getPrimaryCategoryId));
            for (MongoOrderItemBO orderItem : orderBO.getOrderItems()) {
                Long categoryId = categoryMap.get(orderItem.getSpuId());
                orderItem.setPrimaryCategoryId(categoryId);
            }
        }
    }

    private EsOrderBO loadEsOrderBo(Order order) {
        EsOrderBO esOrderBO = mapperFacade.map(order, EsOrderBO.class);
        esOrderBO.setOrderItems(new ArrayList<>());
        // 拼接字符串
        StringBuilder spuCodes = new StringBuilder(500);
        StringBuilder partyCodes = new StringBuilder(500);
        for (OrderItem orderItem : order.getOrderItems()) {
            EsOrderItemBO orderItemVO = mapperFacade.map(orderItem, EsOrderItemBO.class);
            esOrderBO.getOrderItems().add(orderItemVO);
            for (OrderItemLang orderItemLang : orderItem.getOrderItemLangList()) {
                if (Objects.equals(orderItemLang.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang())) {
                    orderItemVO.setSpuNameZh(orderItemLang.getSpuName());
                    orderItemVO.setSkuNameZh(orderItemLang.getSkuName());
                } else if (Objects.equals(orderItemLang.getLang(), LanguageEnum.LANGUAGE_EN.getLang())) {
                    orderItemVO.setSpuNameEn(orderItemLang.getSpuName());
                    orderItemVO.setSkuNameEn(orderItemLang.getSkuName());
                }
            }
            if (StrUtil.isNotBlank(orderItem.getSpuCode())) {
                spuCodes.append(orderItem.getSpuCode()).append(StrUtil.COMMA);
            }
            if (StrUtil.isNotBlank(orderItem.getPartyCode())) {
                partyCodes.append(orderItem.getPartyCode()).append(StrUtil.COMMA);
            }
        }
        if (spuCodes.length() > 1 && spuCodes.lastIndexOf(StrUtil.COMMA) == spuCodes.length() - 1) {
            spuCodes.deleteCharAt(spuCodes.length() - 1);
        }

        if (partyCodes.length() > 1 && partyCodes.lastIndexOf(StrUtil.COMMA) == partyCodes.length() - 1) {
            partyCodes.deleteCharAt(partyCodes.length() - 1);
        }
        esOrderBO.setSpuCodes(spuCodes.toString());
        esOrderBO.setPartyCodes(partyCodes.toString());
        return esOrderBO;
    }

    @Override
    public SendNotifyBO getOrderInfoByOrderId(Long orderId) {
        // 获取订单信息
        EsOrderBO order = orderMapper.getEsOrder(orderId);
        List<com.jf.cloud.common.order.vo.OrderItemVO> orderItems = orderItemService.listOrderItemAndLangByOrderId(orderId);
        StringBuilder sb = new StringBuilder();
        for (com.jf.cloud.common.order.vo.OrderItemVO selectOrderItem : orderItems) {
            String skuName = Objects.isNull(selectOrderItem.getSkuName()) ? "" : selectOrderItem.getSkuName();
            sb.append(selectOrderItem.getSpuName()).append(skuName).append(StrUtil.COMMA);
        }
        sb.deleteCharAt(sb.length() - 1);

        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        sendNotifyBO.setUserId(order.getUserId());
        sendNotifyBO.setBizId(order.getOrderId());
        sendNotifyBO.setMobile(order.getMobile());
        sendNotifyBO.setSpuName(sb.toString());
        sendNotifyBO.setPrice(PriceUtil.toDecimalPrice(order.getActualTotal()).toString());
        sendNotifyBO.setShopId(order.getShopId());
        return sendNotifyBO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWaitPurchaseBatchById(List<Order> orders) {
        if (CollUtil.isEmpty(orders)) {
            return;
        }
        for (Order order : orders) {
            orderMapper.updateWaitPurchase(order);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sourcingOrder(Order order) {
        Order orderDb = getByOrderId(order.getOrderId());
        if (Objects.equals(orderDb.getWaitPurchase(), PurchaseOrderWaitStatus.PURCHASED.value())) {
            log.info("订单已经采购，不需要再次采购");
            return;
        }
        order.setWaitPurchase(PurchaseOrderWaitStatus.PURCHASED.value());
        orderMapper.update(order);
        // 发送消息，订单支付成功 通知商家分账
        PayNotifyBO payNotifyBO = new PayNotifyBO();
        payNotifyBO.setOrderIds(Collections.singletonList(order.getOrderId()));
        payNotifyBO.setAgreePurchase(1);
        ServerResponseEntity<List<Long>> segmentEntity = segmentFeignClient.batchGetSegmentId(DistributedIdKey.MALL4CLOUD_SHOP_WALLET_LOG, payNotifyBO.getOrderIds().size() * 3);
        if (segmentEntity.isFail()) {
            log.info("获取分布式id失败");
            throw new LuckException(segmentEntity.getMsg());
        }
        payNotifyBO.setShopWalletIds(segmentEntity.getData());
        SendStatus sendShopStatus = orderPurchaseNotifyShopTemplate.syncSend(RocketMqConstant.ORDER_PURCHASE_NOTIFY_SHOP_TOPIC, new GenericMessage<>(payNotifyBO)).getSendStatus();
        if (!Objects.equals(sendShopStatus, SendStatus.SEND_OK)) {
            // 消息发不出去就抛异常，因为订单回调会有多次，几乎不可能每次都无法发送出去，发的出去无所谓因为接口是幂等的
            log.info("订单采购后，通知商家分账失败");
            throw new LuckException(ResponseEnum.EXCEPTION);
        }

        //商家采购后，给对应供应商发送待发货提醒
        ServerResponseEntity<List<SendNotifyBO>> orderServerResponseEntity = searchOrderFeignClient.listSendNotifyByOrderIds(Collections.singletonList(order.getOrderId()));
        if (orderServerResponseEntity.isFail()) {
            log.info("获取订单信息失败");
            throw new LuckException(orderServerResponseEntity.getMsg());
        }
        List<SendNotifyBO> notifyList = orderServerResponseEntity.getData();
        for (SendNotifyBO sendNotifyBO : notifyList) {
            sendNotifyBO.setPrice(PriceUtil.toDecimalPrice(sendNotifyBO.getActualTotal()).toString());
            sendNotifyBO.setSendType(SendTypeEnum.USER_PAY_SUCCESS_TO_SUPPLIER.getValue());
            sendNotifyBO.setShopId(null);
        }
        SendStatus sendShopMsgStatus = sendNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyList.get(0))).getSendStatus();
        if (!Objects.equals(sendShopMsgStatus, SendStatus.SEND_OK)) {
            log.info("订单采购后，通知供应商发货失败");
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public List<SendNotifyBO> listSendNotifyBOByOrderIds(List<Long> orderIds) {
        List<OrderVO> orderList = orderMapper.listOrderAndLangByOrderIds(orderIds);
        List<SendNotifyBO> sendNotifyList = new ArrayList<>();
        for (OrderVO orderVO : orderList) {
            SendNotifyBO sendNotifyBO = new SendNotifyBO();
            sendNotifyBO.setShopId(orderVO.getShopId());
            sendNotifyBO.setSupplierId(orderVO.getSupplierId());
            sendNotifyBO.setBizId(orderVO.getOrderId());
            sendNotifyBO.setUserId(orderVO.getUserId());
            sendNotifyBO.setSupplierDeliveryType(orderVO.getSupplierDeliveryType());
            sendNotifyBO.setActualTotal(orderVO.getActualTotal());
            sendNotifyBO.setMobile(orderVO.getMobile());
            OrderLangUtil.orderItemVOList(orderVO.getOrderItems());
            StringBuilder stringBuilder = new StringBuilder();
            for (com.jf.cloud.common.order.vo.OrderItemVO orderItem : orderVO.getOrderItems()) {
                stringBuilder.append(orderItem.getSpuName() + " ");
                if (StrUtil.isNotBlank(orderItem.getSkuName())) {
                    stringBuilder.append(orderItem.getSkuName());
                }
                stringBuilder.append(",");
            }
            if (stringBuilder.length() > 0) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                sendNotifyBO.setSpuName(stringBuilder.toString());
            }
            sendNotifyList.add(sendNotifyBO);
        }
        return sendNotifyList;
    }

    /**
     * 订单语言信息处理
     *
     * @param order 订单
     */
    private void orderLangHandle(Order order) {
        Integer lang = I18nMessage.getLang();
        for (OrderItem orderItem : order.getOrderItems()) {
            if (CollUtil.isEmpty(orderItem.getOrderItemLangList())) {
                continue;
            }
            Map<Integer, OrderItemLang> langMap = orderItem.getOrderItemLangList().stream().collect(Collectors.toMap(OrderItemLang::getLang, s -> s));
            OrderItemLang orderItemLang;
            if (langMap.containsKey(lang)) {
                orderItemLang = langMap.get(lang);
            } else {
                orderItemLang = langMap.get(Constant.DEFAULT_LANG);
            }
            if (Objects.isNull(orderItemLang)) {
                continue;
            }
            orderItem.setSpuName(orderItemLang.getSpuName());
            orderItem.setSkuName(orderItemLang.getSkuName());
        }
    }

    @Override
    public void getReturnOrderStatus(OrderVO orderVO) {
        List<OrderRefund> returnOrderList = orderRefundMapper.getProcessOrderRefundByOrderId(orderVO.getOrderId());
        if (CollUtil.isEmpty(returnOrderList)) {
            return;
        }
        Map<Long, com.jf.cloud.common.order.vo.OrderItemVO> itemVOMap = orderVO.getOrderItems().stream().collect(Collectors.toMap(com.jf.cloud.common.order.vo.OrderItemVO::getOrderItemId, s -> s));
        for (OrderRefund orderRefund : returnOrderList) {
            if (Objects.equals(orderRefund.getRefundType(), RefundType.ALL.value())) {
                orderVO.getOrderItems().forEach(item -> item.setReturnMoneySts(orderRefund.getReturnMoneySts()));
                break;
            } else {
                itemVOMap.get(orderRefund.getOrderItemId()).setReturnMoneySts(orderRefund.getReturnMoneySts());
            }
        }
        return;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderStationByOrderId(List<Long> orderIdList, Long userId, Long stationId) {
        if (CollUtil.isEmpty(orderIdList)) {
            // 请选择最少一个需要自提的订单
            throw new LuckException("请选择最少一个需要自提的订单");
        }
        List<OrderVO> orderList = orderMapper.getStationOrderByOrderIds(orderIdList, userId, null);
        OrderVO orderParam = new OrderVO();
        if (CollectionUtils.isEmpty(orderList)) {
            // 订单不存在
            throw new LuckException("订单不存在");
        }
        for (OrderVO order : orderList) {
            if (Objects.isNull(order)) {
                // 订单不存在
                throw new LuckException("订单不存在");
            }
            orderParam = order;
            if (Objects.equals(order.getOrderMold(), 1)) {
                orderVirtualInfoService.orderWriteOffByOrderId(null, mapperFacade.map(order, Order.class), stationId);
                continue;
            }
            // 如果不是自提订单且不是核销订单就直接报错，如果是扫商家码进来的就不需要自提点id
            if (!Objects.equals(order.getDeliveryType(), DeliveryType.STATION.value()) && !Objects.equals(stationId, null)) {
                // 订单不存在
                throw new LuckException("订单不存在");
            }
            boolean isRefund = Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())
                    || Objects.equals(order.getRefundStatus(), RefundStatusEnum.SUCCEED.value());
            if (Objects.nonNull(order.getRefundStatus()) && isRefund) {
                // 订单退款中，无法自提
                throw new LuckException(order.getOrderId() + "订单退款中，无法自提");
            }
            if (!Objects.equals(order.getStatus(), OrderStatus.PAYED.value())) {
                // 订单已提货
                throw new LuckException(order.getOrderId() + "订单已提货");
            }
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setDeliveryTime(new Date());
            order.setUpdateTime(new Date());
        }
        if (Objects.isNull(stationId)) {
            stationId = orderParam.getStationId();
        }
        StationVO stationVO = stationFeignClient.getStation(stationId).getData();
//        if (!Objects.equals(station.getStatus(), StationStatusEnum.OPEN.value())) {
//            // 该自提点未在营业状态
//            throw new LuckException("yami.shop.station.not.open");
//        }
        List<SendNotifyBO> sendNotifyList = new ArrayList<>();
        List<Long> updateList = new ArrayList<>();
        for (OrderVO orderVO : orderList) {
            if (orderVO.getOrderMold() == null || orderVO.getOrderMold() != 1) {
                updateList.add(orderVO.getOrderId());
            }
            Integer lang = I18nMessage.getLang();
            String spuNames = orderVO.getOrderItems().stream().map(x -> {
                for (OrderItemLangVO itemLang : x.getOrderItemLangList()) {
                    if (Objects.equals(itemLang.getLang(), lang)) {
                        return itemLang.getSpuName();
                    }
                }
                return "";
            }).collect(Collectors.joining(" "));
            // 添加消息通知
            addSendNotify(sendNotifyList, orderVO, spuNames);
        }
        if (updateList.size() != 0) {
            orderMapper.updateByToStatinoSuccess(updateList);
        }
        SendStatus sendStockStatus = sendNotifyToUserTemplate.syncSend(RocketMqConstant.SEND_NOTIFY_TO_USER_TOPIC, new GenericMessage<>(sendNotifyList)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            log.info("自提订单提货后，推送用户消息发送失败");
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        return true;
    }

    private static void addSendNotify(List<SendNotifyBO> sendNotifyList, OrderVO orderVO, String spuNames) {
        // TODO 消息推送-发货提醒,通知其他服务
        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        sendNotifyBO.setUserId(orderVO.getUserId());
        sendNotifyBO.setBizId(orderVO.getOrderId());
        sendNotifyBO.setSpuName(spuNames);
        sendNotifyBO.setShopId(orderVO.getShopId());
        sendNotifyBO.setMobile(orderVO.getMobile());
        sendNotifyBO.setPrice(String.valueOf((orderVO.getActualTotal() / 100)));
        sendNotifyBO.setProdNum(orderVO.getAllCount());
        sendNotifyBO.setDvyName(null);
        sendNotifyBO.setSendType(SendTypeEnum.WRITE_OFF.getValue());
        sendNotifyBO.setDvyFlowId(null);
        sendNotifyList.add(sendNotifyBO);
    }


    @Override
    public List<OrderVO> listStationOrder(OrderDTO orderDTO) {
        return orderMapper.listStationOrder(orderDTO);
    }

    @Override
    public List<Map<String, Object>> countPrimaryCategory(Date startTime,Date endTime) {
        List<Map<String, Object>> cateList = categoryFeignClient.listPrimaryCategoryId().getData();
        for (int i = 0; i < cateList.size(); i++) {
            //每个分类的所有商家ID
            Map<String, Object> map = cateList.get(i);
//            List<Long> listShopId=categoryFeignClient.listByPrimaryCategoryId(Long.valueOf(map.get("category_id").toString())).getData();
            List<OrderOverviewVO> ls = mongoOrderManager.sumByPrimaryCateId(Long.valueOf(map.get("category_id").toString()), startTime, endTime);
            if (null != ls && ls.size() > 0 && null != ls.get(0)) {
                map.put("amount", ls.get(0).getPayActual());
                map.put("total", ls.get(0).getPayOrderCount());
            } else {
                map.put("amount", 0);
                map.put("total", 0);
            }

        }
        return cateList;
    }

    @Override
    public List<OrderOverviewVO> sumGroupByMonth(Date startTime,Date endTime) {

        return mongoOrderManager.sumGroupByMonth(startTime, endTime);

    }

    @Override
    public List<Map<String,Object>> sumGroupByArea(OrderSearchDTO orderSearchDTO) {
        List<Map<String,Object>> list= searchOrderFeignClient.sumOrderGroupArea(orderSearchDTO).getData();
        for (int i = 0; i < list.size(); i++) {
            Map<String,Object> map=list.get(i);
            map.put("name",areaFeignClient.getArea(Long.valueOf(map.get("areaId").toString())).getData().getAreaName());
        }
        return list;
    }

    @Override
    public Map<Long, String> checkShopName(OrderSearchDTO orderSearchDTO) {
        Map<Long, String> shopNameMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        if (null != orderSearchDTO.getShopName() && !Objects.equals(orderSearchDTO.getShopName(), "")) {
            log.info("根据店铺名称查询店铺信息，防止店铺被改名导致的订单数据不准确");
            List<ShopDetailVO> shopList = shopDetailFeignClient.getShopDetailByShopIdAndShopName(orderSearchDTO.getShopName()).getData();
            orderSearchDTO.setShopName(null);
            if (CollUtil.isNotEmpty(shopList)) {
                log.info("将数据库查询的店铺id放入查询条件中");
                shopNameMap.putAll(shopList.stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getShopName)));
                orderSearchDTO.setShopIds(shopList.stream().map(ShopDetailVO::getShopId).collect(Collectors.toList()));
            } else {
                orderSearchDTO.setShopId(Constant.DEFAULT_SHOP_ID);
            }
        }
        return shopNameMap;
    }

    @Override
    public Map<Long, String> checkSupplierName(OrderSearchDTO orderSearchDTO) {
        Map<Long, String> supplierNameMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        if (null != orderSearchDTO.getSupplierName() && !Objects.equals(orderSearchDTO.getSupplierName(), "")) {
            log.info("根据供应商名称查询供应商信息，防止供应商被改名导致的订单数据不准确");
            List<SupplierApiDetailVO> supplierList = supplierDetailFeignClient.getSupplierDetailBySupplierName(orderSearchDTO.getSupplierName()).getData();
            orderSearchDTO.setSupplierName(null);
            if (CollUtil.isNotEmpty(supplierList)) {
                log.info("将数据库查询的店铺id放入查询条件中");
                supplierNameMap.putAll(supplierList.stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, SupplierApiDetailVO::getSupplierName)));
                orderSearchDTO.setSupplierIds(supplierList.stream().map(SupplierApiDetailVO::getSupplierId).collect(Collectors.toList()));
            } else {
                orderSearchDTO.setSupplierId(Constant.DEFAULT_SUPPLIER_ID);
            }
        }
        return supplierNameMap;
    }

    /**
     * 处理自提订单操作
     *
     * @param order   订单
     * @param dvyType 配送方式
     * @param userId  用户id
     */
    private void deliverySubmitOrderListener(ShopCartOrderMergerVO mergerOrder, Order order, Integer dvyType, Long userId) {
        Date now = new Date();
        //判断是否是自提订单
        if (Objects.equals(dvyType, DeliveryType.STATION.value())) {
            //自提订单的地址信息
            OrderSelfStation orderSelfStation = mapperFacade.map(mergerOrder.getOrderSelfStation(), OrderSelfStation.class);
            if (orderSelfStation == null) {
                // 请填写自提信息
                throw new LuckException("请填写自提信息");
            }
            StationVO station = deliveryFeignClient.getStationInfoById(orderSelfStation.getStationId()).getData();
            if (Objects.isNull(station)) {
                // 自提点信息不存在，请重新选择自提点
                throw new LuckException("自提点信息不存在，请重新选择自提点");
            }
            ServerResponseEntity<Long> segmentIdResponse = segmentFeignClient.getSegmentIdWithDateTime(DistributedIdKey.MALL4CLOUD_ORDER_SELF_STATION, userId);
            Long id = segmentIdResponse.getData();
            orderSelfStation.setOrderSelfStationId(id);
            orderSelfStation.setUserId(userId);
            String addr = station.getProvince() + station.getCity() + station.getArea() + station.getAddr();
            //获取最新的随机码
            String code = String.valueOf(Math.random() * 10).substring(0, 1);
            code = code + segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_ORDER).getData();
            code = code.substring(0, 9);
            orderSelfStation.setStationCode(code);
            orderSelfStation.setOrderId(order.getOrderId());
            orderSelfStation.setShopId(order.getShopId());
            orderSelfStation.setStationAddress(addr);
            //若是固定电话，则拼接上区号
            String mobilePrefix = StrUtil.isNotBlank(station.getMobilePrefix()) ? station.getMobilePrefix() : "";
            orderSelfStation.setStationPhone(mobilePrefix + station.getMobile());
            orderSelfStation.setCreateTime(now);
            orderSelfStation.setUpdateTime(now);
            orderSelfStationService.save(orderSelfStation);
        }
    }

    /**
     * 处理虚拟商品操作
     *
     * @param mergerOrder      聚合订单信息
     * @param shopCartOrderDto 店铺订单信息
     * @param order            订单信息
     */
    private void handlerVirtualProdOder(ShopCartOrderMergerVO mergerOrder, ShopCartOrderVO shopCartOrderDto, Order order, Long userId) {
        OrderItem orderItem = order.getOrderItems().get(0);
        order.setOrderMold(orderItem.getSpuMold());
        orderItem.setIsRefund(shopCartOrderDto.getIsRefund());
        Map<Long, List<VirtualRemarkVO>> map = new HashMap<>(8);
        Long prodId = shopCartOrderDto.getShopCartItemDiscounts().get(0).getShopCartItems().get(0).getSpuId();
        // 虚拟商品备注信息列表
        if (CollUtil.isNotEmpty(mergerOrder.getVirtualRemarkList())) {
            for (VirtualRemarkVO virtualRemarkVO : mergerOrder.getVirtualRemarkList()) {
                if (Objects.isNull(virtualRemarkVO.getSpuId())) {
                    virtualRemarkVO.setSpuId(prodId);
                }
            }
            map = mergerOrder.getVirtualRemarkList().stream().collect(Collectors.groupingBy(VirtualRemarkVO::getSpuId));
        }
        if (Objects.equals(order.getOrderMold(), 1)) {
            // 存入留言
            String virtualRemarkStr = Json.toJsonString(map.get(prodId));
            orderItem.setVirtualRemark(virtualRemarkStr);
            // 虚拟商品默认无需快递
            order.setDeliveryType(DeliveryType.NOT_DELIVERY.value());
            // 存入核销信息
            order.setWriteOffStart(shopCartOrderDto.getWriteOffStart());
            order.setWriteOffEnd(shopCartOrderDto.getWriteOffEnd());
            if (Objects.nonNull(shopCartOrderDto.getWriteOffEnd()) && DateUtil.compare(shopCartOrderDto.getWriteOffEnd(), new Date()) < 0) {
                throw new LuckException("卡券已过期！");
            }
            order.setWriteOffNum(shopCartOrderDto.getWriteOffNum());
            order.setWriteOffMultipleCount(shopCartOrderDto.getWriteOffMultipleCount());
            order.setWriteOffStatus(0);
            if (Objects.equals(order.getWriteOffNum(), 0)) {
                return;
            }
            List<OrderVirtualInfo> orderVirtualInfos = new ArrayList<>();
            for (int i = 0; i < order.getAllCount(); i++) {
                OrderVirtualInfo orderVirtualInfo = new OrderVirtualInfo();
                ServerResponseEntity<Long> segmentIdResponse = segmentFeignClient.getSegmentIdWithDateTime(DistributedIdKey.MALL4CLOUD_ORDER_VIRTUAL_INFO, userId);
                Long id = segmentIdResponse.getData();
                orderVirtualInfo.setOrderVirtualInfoId(id);
                orderVirtualInfo.setOrderId(order.getOrderId());
                orderVirtualInfo.setShopId(order.getShopId());
                orderVirtualInfo.setIsWriteOff(0);
                orderVirtualInfo.setWriteOffMultipleCount(order.getWriteOffMultipleCount());
                //获取最新的随机码
                String code = String.valueOf(Math.random() * 10).substring(0, 1);
                code = code + segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_ORDER).getData();
                code = code.substring(0, 9);
                orderVirtualInfo.setWriteOffCode(code);
                orderVirtualInfo.setCreateTime(new Date());
                orderVirtualInfos.add(orderVirtualInfo);
            }
            orderVirtualInfoService.saveBatch(orderVirtualInfos);
        }
    }
}
